home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / TPLIB21 / MANUAL.PRN < prev    next >
Encoding:
Text File  |  1993-06-24  |  272.6 KB  |  6,557 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.                                TURBO PASCAL LIBRARY
  11.  
  12.                                    Version 2.1
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.                                    Paul Coxwell
  49.                                   30 Alford Road
  50.                                   Sutton-on-Sea
  51.                                      LN12 2HH
  52.                                      England
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.           ************************************************************
  62.           *                                                          *
  63.           *                    TURBO PASCAL LIBRARY                  *
  64.           *                        Version 2.1                       *
  65.           *                         June 1993                        *
  66.           *                                                          *
  67.           *    A library of routines for Borland's Pascal compiler   *
  68.           *                                                          *
  69.           ************************************************************
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.               This  package  may  be  freely  copied  and   distributed
  80.           provided  that  all   files,  including  documentation,   are
  81.           supplied intact.   No fee in  excess of a  minimal amount  to
  82.           cover costs may be charged for such distribution.
  83.  
  84.               All warranties, express or implied, including fitness for
  85.           any particular  purpose, are  disclaimed.   The user  assumes
  86.           full responsibility  for  ensuring the  suitability  of  this
  87.           software.
  88.  
  89.               No registration fee  is required or  requested.  You  are
  90.           free to use this package without payment.
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.                       Copyright (C) 1991, 1993  Paul Coxwell
  107.                                All rights reserved
  108.  
  109.                                 TABLE OF CONTENTS
  110.           =============================================================
  111.  
  112.  
  113.           1.  INTRODUCTION                                           1
  114.  
  115.  
  116.           2.  UNIT STRINGS                                           3
  117.                   Global declarations                                3
  118.                   LoCase                                             4
  119.                   UpperCase                                          4
  120.                   LowerCase                                          4
  121.                   DuplChar                                           4
  122.                   DuplStr                                            4
  123.                   TrimL                                              5
  124.                   TrimR                                              5
  125.                   PadL                                               5
  126.                   PadR                                               5
  127.                   TruncL                                             5
  128.                   TruncR                                             5
  129.                   JustL                                              6
  130.                   JustR                                              6
  131.                   JustC                                              6
  132.  
  133.                   Precede                                            7
  134.                   Follow                                             7
  135.                   Break                                              7
  136.                   Span                                               8
  137.                   Replace                                            8
  138.                   Remove                                             9
  139.                   StripBit7                                          9
  140.                   FileSpecDefault                                    9
  141.                   HexStr                                            10
  142.                   OctStr                                            10
  143.                   BinStr                                            10
  144.  
  145.                   Format                                            10
  146.                           Sign options                              11
  147.                           Justification and fill options            12
  148.                           Display of vulgar fractions               13
  149.                           Control string summary                    15
  150.  
  151.  
  152.           3.  UNIT MATH & MATH87                                    17
  153.                   FahrToCent                                        17
  154.                   CentToFahr                                        17
  155.                   KelvToCent                                        17
  156.                   CentToKelv                                        17
  157.  
  158.                   InchToFtIn                                        18
  159.                   FtInToInch                                        18
  160.                   InchToYard                                        18
  161.                   YardToInch                                        18
  162.                   InchToMile                                        19
  163.                   MileToInch                                        19
  164.                   InchToNautMile                                    19
  165.                   NautMileToInch                                    19
  166.                   InchToMeter                                       19
  167.                   MeterToInch                                       19
  168.  
  169.                   SqInchToSqFeet                                    19
  170.                   SqFeetToSqInch                                    19
  171.                   SqInchToSqYard                                    19
  172.                   SqYardToSqInch                                    19
  173.                   SqInchToSqMile                                    19
  174.                   SqMileToSqInch                                    19
  175.                   SqInchToAcre                                      19
  176.                   AcreToSqInch                                      19
  177.                   SqInchToSqMeter                                   20
  178.                   SqMeterToSqInch                                   20
  179.  
  180.                   CuInchToCuFeet                                    20
  181.                   CuFeetToCuInch                                    20
  182.                   CuInchToCuYard                                    20
  183.                   CuYardToCuInch                                    20
  184.                   CuInchToCuMeter                                   20
  185.                   CuMeterToCuInch                                   20
  186.  
  187.                   FluidOzToPint                                     20
  188.                   PintToFluidOz                                     20
  189.                   FluidOzToGals                                     20
  190.                   GalsToFluidOz                                     20
  191.                   FluidOzToImpPint                                  20
  192.                   ImpPintToFluidOz                                  20
  193.                   FluidOzToImpGals                                  20
  194.                   ImpGalsToFluidOz                                  20
  195.                   FluidOzToCuMeter                                  21
  196.                   CuMetersToFluidOz                                 21
  197.  
  198.                   OunceToLbOz                                       21
  199.                   LbOzToOunce                                       21
  200.                   OunceToTon                                        21
  201.                   TonToOunce                                        21
  202.                   OunceToLongTon                                    21
  203.                   LongTonToOunce                                    21
  204.                   OunceToGram                                       21
  205.                   GramToOunce                                       21
  206.  
  207.  
  208.           4.  UNIT TIME                                             23
  209.                   Global declarations                               23
  210.                   CombineDateTime                                   24
  211.                   SplitDateTime                                     24
  212.                   GetToDay                                          25
  213.                   GetTimeNow                                        25
  214.                   GetDateTime                                       25
  215.  
  216.                   DateValid                                         25
  217.                   TimeValid                                         25
  218.                   DateTimeValid                                     26
  219.                   WordToDate                                        26
  220.                   DateToWord                                        26
  221.                   LeapYear                                          27
  222.                   TimeAP                                            27
  223.                   AdjustDate                                        27
  224.                   AdjustTime                                        27
  225.                   AdjustDateTime                                    28
  226.                   SetLastDay                                        28
  227.  
  228.                   DayOfWeek                                         28
  229.                   DayOfWeekStr                                      29
  230.                   MonthStr                                          29
  231.                   DayOfMonthStr                                     29
  232.                   DateStr                                           29
  233.                   FullDateStr                                       31
  234.                   TimeStr                                           31
  235.                   DateParse                                         33
  236.                   TimeParse                                         35
  237.  
  238.  
  239.           5.  UNIT STDERR                                           39
  240.                   WriteStdErr                                       39
  241.  
  242.  
  243.           6.  UNIT CRTCLERR                                         41
  244.                   CriticalErrorDOS                                  42
  245.                   CriticalErrorTP                                   42
  246.                   CriticalErrorOwn                                  42
  247.                   CriticalErrorMsg                                  42
  248.  
  249.  
  250.           7.  UNIT ENHCON                                           45
  251.                   Display attribute constants                       46
  252.                   Extended key handling and ReadKey function        46
  253.  
  254.                   ColorDisplay                                      48
  255.                   GetMaxXY                                          49
  256.                   GetDisplayPage                                    49
  257.                   GetDisplayBase                                    49
  258.                   MaxCursorSize                                     49
  259.                   SetCursor                                         50
  260.                   GetCursor                                         50
  261.                   HideCursor                                        51
  262.                   CursorHidden                                      51
  263.                   LineCursor                                        51
  264.                   BlockCursor                                       51
  265.                   Insert/overwrite cursor switching                 52
  266.                   OrigCursor                                        52
  267.  
  268.                   CapsLock                                          53
  269.                   NumLock                                           53
  270.                   ScrollLock                                        53
  271.                   InsertLock                                        53
  272.                   ForceInsert                                       53
  273.                   FlushKB                                           53
  274.  
  275.                   Editing routines                                  54
  276.                   EditString                                        54
  277.                           Marking the field                         55
  278.                           Basic editing                             56
  279.                           Restore and abort                         57
  280.                           Flags                                     58
  281.                           Insert and overwrite modes                58
  282.                           Field clearing and edit keys              59
  283.                           Cursor control                            60
  284.                           String formatting                         61
  285.                           Miscellaneous configuration control       62
  286.  
  287.                   EditReal                                          62
  288.                           Exponential notation                      63
  289.                           Range and conversion errors               64
  290.                   EditInt                                           65
  291.                   EditDate                                          66
  292.                   EditTime                                          66
  293.  
  294.                   Using display windows                             67
  295.                   Window zero                                       70
  296.                   DefineWindow                                      70
  297.                   OpenWindow                                        71
  298.                   SelectWindow                                      72
  299.                   CloseWindow                                       72
  300.                   HideWindow                                        73
  301.                   ShowWindow                                        73
  302.                   RelocateWindow                                    74
  303.                   MoveWindow                                        74
  304.                   WriteWindow                                       75
  305.                   CurrentWindow                                     75
  306.                   WindowStat                                        75
  307.                   PurgeWindow                                       75
  308.                   GetWindowDef                                      76
  309.                   Windows error handling                            76
  310.                   WindowResult                                      77
  311.                   ConErrorMsg                                       78
  312.  
  313.                   The on-line help system                           78
  314.                   Creating the help file                            78
  315.                   HelpInitialize                                    80
  316.                   Index layout                                      83
  317.                   Using help                                        83
  318.                   General help                                      83
  319.                   Context-sensitive help                            84
  320.                   PushHelpContext                                   85
  321.                   PopHelpContext                                    85
  322.                   Last-help facility                                85
  323.                   Moving the help window                            86
  324.                   HelpReset                                         86
  325.                   Help system error handling                        87
  326.                   Restrictions and TextMode                         89
  327.  
  328.  
  329.           APPENDIX A.  UNIT INTERFACES                              91
  330.  
  331.  
  332.           APPENDIX B.  CODE DEPENDENCIES                           105
  333.  
  334.  
  335.           APPENDIX C.  REVISION HISTORY                            107
  336.  
  337.  
  338.           APPENDIX D.  DISTRIBUTION POLICY                         111
  339.  
  340.  
  341.                                         1.
  342.                                    INTRODUCTION 
  343.           =============================================================
  344.  
  345.  
  346.               Welcome to Turbo Pascal Library, a collection of routines
  347.           to  ease  the  development   of  application  programs   with
  348.           Borland's Turbo Pascal compiler.  This version of the library
  349.           contains units covering  string manipulation,  date and  time
  350.           conversion and  formatting, routines  for the  conversion  of
  351.           units of  measurement, improved  error handling,     enhanced
  352.           console input/output, windows, and an on-line help system.
  353.  
  354.               Turbo Pascal Library requires an  IBM  PC or  compatible,
  355.           DOS version 2.0 or  later, and Turbo   Pascal version 5.0  or
  356.           later.   A fixed disk  drive is not essential, but is  highly
  357.           recommended for  any  serious  development    work.      Some
  358.           portions   of the   library   are  written in  assembler;  to
  359.           modify these you   will  need a   standard  8086   assembler,
  360.           such  as   Borland's  Turbo  Assembler.     The  intermediate
  361.           object  code  files are  included   so that  you  can  modify
  362.           and recompile the Pascal  source code without  access to   an
  363.           assembler.
  364.  
  365.               The files  that  comprise  this package  are  stored   on
  366.           the distribution diskette in  compressed form.   To   extract
  367.           all  the code enter the command
  368.  
  369.                           INSTALL C:\PATH
  370.  
  371.           where "C:\PATH"  is the  drive and  path where  you want  the
  372.           files to be placed.   Because of  the incompatibility of  TPU
  373.           files  compiled under different  versions  of  Turbo  Pascal,
  374.           no  TPU   files   are supplied.   A batch   file is  included
  375.           which   will compile  all the  units using  the  command-line
  376.           version of the compiler (TPC).
  377.  
  378.               You should  copy the  TPU files  to a  directory that  is
  379.           searched by  Turbo  Pascal when  compiling  a program.    You
  380.           should also ensure  that the OBJ  files  are  in a  directory
  381.           that will be searched  at  link time if you intend to  modify
  382.           the units in any way.
  383.  
  384.               The code  in this  package   is released  for public  use
  385.           without payment.  You are  free to use, copy, and  distribute
  386.           this  package as widely as  you wish.   Your  comments  about
  387.           this package   and suggestions for   future   revisions   are
  388.           always  welcome.  The  address to write to  is shown on   the
  389.           cover of this manual.
  390.  
  391.  
  392.                                   HAPPY PROGRAMMING!
  393.  
  394.           
  395.           
  396.                                        -1-  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.           
  451.           
  452.                                        -2-  
  453.                                         2.
  454.                                   UNIT STRINGS 
  455.           =============================================================
  456.  
  457.               Turbo Pascal  provides  a fairly  standard  selection  of
  458.           string-handling procedures and functions.  This unit  expands
  459.           upon  those routines  defined  by  Turbo  Pascal  and  offers
  460.           routines    for manipulating strings  in a   number of  ways:
  461.           replication,        padding,    truncation,    justification,
  462.           replacement, and so on.
  463.  
  464.  
  465.           GLOBAL DECLARATIONS
  466.  
  467.               The  following  constant  strings  are  defined  in   the
  468.           interface section of the unit:
  469.  
  470.                   UCaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  471.                   LCaseLetters = 'abcdefghijklmnopqrstuvwxyz';
  472.                   Letters      = UCaseLetters + LCaseLetters;
  473.                   DecDigits    = '0123456789';
  474.                   HexDigits    = '0123456789ABCDEF';
  475.                   OctDigits    = '01234567';
  476.                   BinDigits    = '01';
  477.  
  478.           These  will  be  found  useful   with  many  of  the   string
  479.           manipulation routines.
  480.  
  481.               The unit also defines  a new type  and a global  variable
  482.           which consists of four fields:
  483.  
  484.                   FormatConfigRec = RECORD
  485.                                           Fill,
  486.                                           Currency,
  487.                                           Overflow,
  488.                                           FracSep:        CHAR;
  489.                                     END;
  490.  
  491.                   FormatConfig: FormatConfigRec =
  492.                                           (Fill:     '*';
  493.                                            Currency: '$';
  494.                                            Overflow: '?';
  495.                                            FracSep:  '-');
  496.  
  497.           This global variable is used by the Format function, and  the
  498.           fields are described in detail when appropriate.
  499.  
  500.           -------------------------------------------------------------
  501.  
  502.  
  503.  
  504.  
  505.  
  506.           
  507.           
  508.                                        -3-  
  509.           FUNCTION LoCase (ch: CHAR): CHAR;
  510.  
  511.               Turbo Pascal  provides  an  UpCase function  to   convert
  512.           any character to its upper-case   equivalent.  This  function
  513.           performs the converse  function and converts  a character  to
  514.           its  lower-case equivalent.
  515.  
  516.               The character supplied  as parameter ch  is converted  to
  517.           lower case and  returned as  the function's  result.   If the
  518.           supplied character  is   already lower    case   or is    not
  519.           alphabetic,  it  is returned unchanged.
  520.  
  521.           -------------------------------------------------------------
  522.  
  523.           FUNCTION UpperCase (s: STRING): STRING; 
  524.           FUNCTION LowerCase (s: STRING): STRING;
  525.  
  526.               These two   functions perform   case  conversion  on   an
  527.           entire string  of  characters.     The   returned  string  is
  528.           always equal   in  length  to the  supplied string,  and  all
  529.           alphabetic characters  are converted  to upper or lower  case
  530.           as appropriate.    Non-alphabetic  characters, or  characters
  531.           which are already in the required case, are not changed.
  532.  
  533.           -------------------------------------------------------------
  534.  
  535.           FUNCTION DuplChar (ch: CHAR; count: BYTE): STRING;
  536.  
  537.               DuplChar  returns   a  string   of  characters   of   the
  538.           length  requested  in  parameter  count.      The   character
  539.           supplied in ch  is used to build  the  string.  If  count  is
  540.           zero,  a null string  is returned.
  541.  
  542.           -------------------------------------------------------------
  543.  
  544.           FUNCTION DuplStr (s: STRING; count: BYTE): STRING;
  545.  
  546.               This function is  similar to DuplChar,  but duplicates  a
  547.           string of  characters instead  of a  single character.    The
  548.           returned  string  comprises  the     supplied  string,     s,
  549.           concatenated to   itself   the number of  times specified  by
  550.           count.
  551.  
  552.               Note that the maximum length of  a string in Turbo Pascal
  553.           is 255 characters.    If  the   length of   s  multiplied  by
  554.           count  is greater than  255, then  the returned  string  will
  555.           be  truncated after the 255th character.   If count is  zero,
  556.           a null string  is returned.
  557.  
  558.           -------------------------------------------------------------
  559.  
  560.  
  561.  
  562.           
  563.           
  564.                                        -4-  
  565.           FUNCTION TrimL (s: STRING): STRING; 
  566.           FUNCTION TrimR (s: STRING): STRING;
  567.  
  568.               These two functions   allow  blanks to   be trimmed  from
  569.           either the beginning  or  end  of  a  string  of  characters.
  570.           TrimL  (Trim Left)  returns  the  supplied  string  with  all
  571.           leading   blanks removed.   TrimR  (Trim Right)  returns  the
  572.           supplied string with all trailing  blanks removed.  If  there
  573.           are no blanks, the string  is returned unchanged.
  574.  
  575.               Both functions  regard a  space (ASCII  code 32  decimal,
  576.           20 hex.)  and a    tab (ASCII  code   9)  as being    blanks;
  577.           trimming   will stop  as  soon as  any  other   character  is
  578.           encountered.  Both  TrimL and TrimR return a null string if s
  579.           is a null string or  consists of spaces and tabs only.
  580.  
  581.           -------------------------------------------------------------
  582.  
  583.           FUNCTION PadL (s: STRING; width: BYTE): STRING; 
  584.           FUNCTION PadR (s: STRING; width: BYTE): STRING;
  585.  
  586.               PadL (Pad Left)  and PadR (Pad  Right) allow a  string to
  587.           be padded out to a specified length by the addition of spaces
  588.           to the start  or end of  the supplied string,  s.  PadL  adds
  589.           spaces  (ASCII code 20 hex.) to  the start of  the string  to
  590.           make  it up to  the length supplied in parameter width.  PadR
  591.           adds spaces to the   end of the string to  make it up to  the
  592.           requested width.
  593.  
  594.               If spaces or tabs are already present at the start or end
  595.           of the supplied string  they are not removed.   To justify  a
  596.           string by  removing existing  blanks  and then  adding  those
  597.           required, use  the justify functions described below.
  598.  
  599.               If the  supplied   string is   a  null, both    functions
  600.           return  a string of spaces of the specified  length.  If  the
  601.           length of  the supplied string is already equal to or greater
  602.           than the specified width it is returned unchanged.  PadL  and
  603.           PadR will never  return a string of  less than the  specified
  604.           width, but  may return  one which is longer.
  605.  
  606.           -------------------------------------------------------------
  607.  
  608.           FUNCTION TruncL (s: STRING; width: BYTE): STRING; 
  609.           FUNCTION TruncR (s: STRING; width: BYTE): STRING;
  610.  
  611.               These functions   truncate a   string to   the  specified
  612.           width. TruncL removes characters from the  start of a  string
  613.           and  TruncR removes them from the end.
  614.  
  615.               Both functions return a null string if width is specified
  616.           as zero, and  both   functions return  the  string  unchanged
  617.           if  its  length is   already less   than  or  equal  to   the
  618.           
  619.           
  620.                                        -5-  
  621.           specified  width.  TruncL and   TruncR will  never return   a
  622.           string  longer than  the specified width, but may, therefore,
  623.           return one which is shorter.
  624.  
  625.           -------------------------------------------------------------
  626.  
  627.           FUNCTION JustL (s: STRING; width: BYTE): STRING; 
  628.           FUNCTION JustR (s: STRING; width: BYTE): STRING;
  629.  
  630.               These justification  functions  combine the  effects   of
  631.           the trim, pad, and truncate functions described above.
  632.  
  633.               JustL ensures   that   a    string is   left    justified
  634.           within  a specified field  width.    All blanks  are  removed
  635.           from both  the  beginning and  end   of  the   string.    The
  636.           remaining  string   is truncated from  the  right  if  it  is
  637.           too long  for the  requested width or spaces are added to the
  638.           end of the string if it is  too short.
  639.  
  640.               JustR ensures   that    a string    is   right  justified
  641.           within  a specified field  width.    All blanks  are  removed
  642.           from both  the beginning  and end  of  the  string, then  the
  643.           remaining string   is truncated from  the left if  it is  too
  644.           long for the requested width or spaces are added to the  left
  645.           of the string if it is too short.
  646.  
  647.               JustL is equivalent  to TrimL,   TrimR, TruncR, and  PadR
  648.           being applied to   a  string,  in  that   order.    JustR  is
  649.           equivalent   to  TrimL,  TrimR,    TruncL,  PadL.        Both
  650.           functions,  therefore,  will  always  return   a  string   of
  651.           the  specified   length  by   either truncating the  supplied
  652.           string or  padding  it as  required.    If  width is zero,  a
  653.           null string is returned.
  654.  
  655.           -------------------------------------------------------------
  656.  
  657.           FUNCTION JustC (s: STRING; width: BYTE): STRING;
  658.  
  659.               JustC (Justify  Center)   positions a   string  centrally
  660.           within the specified field width.
  661.  
  662.               First, leading and  trailing blanks are  trimmed and  the
  663.           string is truncated   from the   right if   it is   too  long
  664.           (this part  is identical  to the  JustL  function).   If  the
  665.           remaining string  is shorter than the requested length spaces
  666.           are added equally to the left and right of the string to make
  667.           it up to the required width.
  668.  
  669.               If the  trimmed  and  truncated string  contains  an  odd
  670.           number of characters  and the   requested width   is an  even
  671.           number, or  vice versa,  it will not be  possible  to add  an
  672.           equal number of  spaces to the left and right  of the  string
  673.           in order  to center it.    In such cases,  JustC places   the
  674.           
  675.           
  676.                                        -6-  
  677.           extra   "odd"  space   at  the   right,  leaving  the  string
  678.           justified slightly to the left.
  679.  
  680.               JustC, like JustL and JustR,  will always return a string
  681.           of the specified length.   If  width is  specified as   zero,
  682.           a  null string is returned.
  683.  
  684.           -------------------------------------------------------------
  685.  
  686.           FUNCTION Precede (s, target: STRING): STRING;
  687.  
  688.               Precede searches  for a    sub-string, target,  within  a
  689.           string, s.   If    the search  is   successful  the  function
  690.           returns a  string  consisting of all the   characters up  to,
  691.           but not  including,   the  target string.     If  the  target
  692.           string is  not    found,  the    entire  string  is  returned
  693.           unchanged.
  694.  
  695.           -------------------------------------------------------------
  696.  
  697.           FUNCTION Follow (s, target: STRING): STRING;
  698.  
  699.               Follow  searches  for  a  sub-string,  target,  within  a
  700.           string, s. If the   target string   is   found the   function
  701.           returns  a   string consisting  of all the  characters   that
  702.           follow the search   string.  If the  search is  unsuccessful,
  703.           Follow returns a null string.
  704.  
  705.           -------------------------------------------------------------
  706.  
  707.           FUNCTION Break (VAR s: STRING; d: STRING): STRING;
  708.  
  709.               The Break function  emulates the   function of  the  same
  710.           name found in the SNOBOL programming language.
  711.  
  712.               A string to be  parsed is supplied as  parameter s and  a
  713.           set of delimiter  characters is   supplied as   parameter  d.
  714.           Break  scans string s for the first of  any of the  delimiter
  715.           characters in    d. The  returned  string   consists  of  all
  716.           characters in the  supplied string up to, but not  including,
  717.           the delimiter character  found.  In addition, Break  modifies
  718.           the  string s  so as  to remove  the characters preceding the
  719.           delimiter (i.e. the  characters  returned  by Break are  also
  720.           removed from the source string).
  721.  
  722.               Note that  the  order of  the  characters in  the  string
  723.           of delimiters is unimportant; Break scans  until it finds the
  724.           first of any of the  characters.   If no  delimiter is  found
  725.           during  the search, Break returns the entire input string and
  726.           sets the  input string to a null.
  727.  
  728.           -------------------------------------------------------------
  729.  
  730.           
  731.           
  732.                                        -7-  
  733.           FUNCTION Span (VAR s: STRING; d: STRING): STRING;
  734.  
  735.               Span also  emulates  a SNOBOL  function,  and is  similar
  736.           in operation to Break.  The difference  is that Span searches
  737.           for   a character  which is    not specified   in  string  d,
  738.           rather than  one that is.
  739.  
  740.               Span  searches  the  input   string,  s,  checking   that
  741.           each character of s  is also present in  string d.  The  scan
  742.           stops  when  a character is  found in  s which is   not  also
  743.           present in d.   Span then returns all the characters  scanned
  744.           and, like Break,  removes them from the source string, s.
  745.  
  746.               As  with  Break,  the  order  in  which  the   characters
  747.           are specified in d has no  effect on the outcome of the  call
  748.           to   Span. If  every   character in   the  input   string  is
  749.           listed in  d,  Span returns the entire string and sets s to a
  750.           null string.
  751.  
  752.               Break and Span provide a very powerful way to parse input
  753.           and remove each  element   as  it   is  dealt   with.     The
  754.           string constants listed in the introduction to this unit will
  755.           be found helpful for such applications.
  756.  
  757.           -------------------------------------------------------------
  758.  
  759.           FUNCTION Replace (s, srch, repl: STRING): STRING;
  760.  
  761.               Replace also  closely emulates   a  SNOBOL function;  the
  762.           source string, s,  is searched   for any of  the   characters
  763.           listed in  the string srch.  When such a character is  found,
  764.           it is replaced by a character in the string repl.  The search
  765.           is continued until  the end of the string is reached.
  766.  
  767.               Strings srch and  repl should  be  equal  in length,  and
  768.           when  a character in srch is  located it  is replaced by  the
  769.           character  in the equivalent  position in repl (e.g. if  srch
  770.           contains 'ABC'   and  repl contains  'XYZ' then   an  'A'  is
  771.           replaced  with an 'X',  a  'B' with a  'Y', and a 'C' with  a
  772.           'Z').  The function returns a string of the same length as s,
  773.           but with all requested substitutions  in place.
  774.  
  775.               Note that  if  repl   is  longer than   srch,  then   the
  776.           extra characters in  repl are  ignored.   Similarly, if   the
  777.           length  of string srch  is greater  than  that of  repl,  the
  778.           extra  characters specified  in srch are  not searched   for.
  779.           If either srch or  repl is a null string, Replace will return
  780.           the input string unchanged.
  781.  
  782.           -------------------------------------------------------------
  783.  
  784.  
  785.  
  786.           
  787.           
  788.                                        -8-  
  789.           FUNCTION Remove (s, srch: STRING): STRING;
  790.  
  791.               Remove  searches  the  source  string,  s,  for  any   of
  792.           the characters listed in  srch.   The  returned string is   s
  793.           with  all such characters removed.
  794.  
  795.               The order in which the characters are listed in srch does
  796.           not matter;  all characters  matching  those listed  will  be
  797.           deleted.  If  srch is a  null string or  the supplied  string
  798.           contains none of  the characters  listed in srch,  then s  is
  799.           returned unchanged.
  800.  
  801.           -------------------------------------------------------------
  802.  
  803.           FUNCTION StripBit7 (s: STRING): STRING;
  804.  
  805.               This function returns the supplied string with the  high-
  806.           order bit of each  character cleared.   This converts   ASCII
  807.           codes  128 through 255  (decimal)  to codes  0  through  127,
  808.           thus  changing symbols and  foreign characters  to   standard
  809.           7-bit  ASCII  code.  Another use would  be to strip  a parity
  810.           bit  from data  received over a communication channel.
  811.  
  812.               The returned  string is  always equal  in length  to  the
  813.           supplied string  and  characters  which are  already  in  the
  814.           conventional  ASCII   set  (0   through  127   decimal)   are
  815.           unaffected.
  816.  
  817.           -------------------------------------------------------------
  818.  
  819.           FUNCTION FileSpecDefault (s,path,name,extn: STRING): STRING;
  820.  
  821.               This function is specifically  designed to enable  user's
  822.           input of a file path and name to be processed, and allow  any
  823.           section which  is  absent from  the  input  to be  set  to  a
  824.           predetermined string.
  825.  
  826.               The user's  input  should  be  passed  as  parameter   s,
  827.           and defaults for the path, name, and file extension should be
  828.           passed in path, name, and extn, respectively.  Turbo Pascal's
  829.           FSplit procedure is used to break the user's input into three
  830.           sections.  If any section is missing from the user's input it
  831.           is taken  from the supplied defaults; FileSpecDefault returns
  832.           a string with  the three sections re-assembled.
  833.  
  834.               When  specifying  the   default  path,   ensure  that   a
  835.           final backslash is  included if  required.   Similarly,   the
  836.           extension should include the leading period delimiter.
  837.  
  838.           -------------------------------------------------------------
  839.  
  840.  
  841.  
  842.           
  843.           
  844.                                        -9-  
  845.           FUNCTION HexStr (n: WORD; count: BYTE): STRING; 
  846.           FUNCTION OctStr (n: WORD; count: BYTE): STRING; 
  847.           FUNCTION BinStr (n: WORD; count: BYTE): STRING;
  848.  
  849.               These three functions  allow an  integer in  the range  0
  850.           through 65,535  to  be  coverted  to  a  string  holding  the
  851.           hexadecimal, octal, or binary representation of the number.
  852.  
  853.               The  number  to  be  converted  should  be  supplied   in
  854.           parameter  n and the number of hexadecimal,  octal, or binary
  855.           digits  required in the string should be passed in  parameter
  856.           count.   Each  function  returns  a string  of  the    length
  857.           specified by count, with   leading zeros if necessary.   Note
  858.           that if the number of digits   specified is  not   sufficient
  859.           to   represent   the   number   then   the   most-significant
  860.           digits are lost.
  861.  
  862.           -------------------------------------------------------------
  863.  
  864.           FUNCTION Format (n: REAL; form: STRING): STRING;
  865.  
  866.               Although the  standard   Write  and WriteLn    procedures
  867.           allow  a number to   be output  to   any given  field   width
  868.           and   number   of decimal  places, more   control  over   the
  869.           display  and printing  of numbers is often required.
  870.  
  871.               Format takes  the  number  passed   in  parameter  n  and
  872.           returns  a string suitable for printing.  The contents of the
  873.           parameter form determine the exact way in which the output is
  874.           formatted.     The  variable  FormatConfig,  defined  in  the
  875.           interface section of the unit, also controls the way in which
  876.           some features  work.   This  variable contains  four  fields:
  877.           Fill, Currency, Overflow, and  FracSep.  These are  described
  878.           below when appropriate.
  879.  
  880.               The basic formatting string  closely resembles that  used
  881.           with Write and WriteLn.   Two numbers, separated  by a colon,
  882.           specify the total width of the returned string and the number
  883.           of  decimal places.   The format string '10:2', for  example,
  884.           specifies a total width of 10 characters and that the  number
  885.           should be rounded to 2 decimal places.   If either  number is
  886.           omitted,  or invalid,  the  default values are a total  width
  887.           of 12  characters  and zero  decimal  places.     The  format
  888.           strings   '8' and   '8:0',  for   example,   are  equivalent.
  889.           Format will always  return a  string equal in  length to  the
  890.           width  specified.  If   the width is   insufficient for   the
  891.           number being formatted, the returned field is filled with  an
  892.           overflow warning  character,  which defaults  to  a  question
  893.           mark.  You can change this character by making an  assignment
  894.           to the Overflow field of FormatConfig.
  895.  
  896.  
  897.  
  898.           
  899.           
  900.                                       -10-  
  901.                   Format (25.631, '8:2')      returns '   25.63'
  902.                   Format (-46.9, '4')         returns ' -47'
  903.                   Format (1000, '3')          returns '???'
  904.  
  905.  
  906.           SIGN OPTIONS
  907.  
  908.               Format  offers several different  ways  to  display   the
  909.           sign (positive or negative)  of a  number.   The default   is
  910.           to  prefix negative numbers   with  a   minus  sign.  If  the
  911.           format string  contains a leading "+"  then a sign  is  added
  912.           even if the number is positive.
  913.  
  914.                   Format (-8.3, '6:1')        returns '  -8.3'
  915.                   Format (8.3, '6:1')         returns '   8.3'
  916.                   Format (-20.4, '+6:1')      returns ' -20.4'
  917.                   Format (20.4, '+6:1')       returns ' +20.4'
  918.  
  919.  
  920.               The sign  may also    be placed  after  the   number,  by
  921.           putting  a "+" or "-" at the  end of the format  string.  The
  922.           former  option  causes positive  and negative  numbers to  be
  923.           displayed with a sign; the  latter formats  positive  numbers
  924.           with a   trailing space   for  ease of  alignment of  printed
  925.           columns.
  926.  
  927.                   Format (-32, '5-')          returns '  32-'
  928.                   Format (32, '5-')           returns '  32 '
  929.                   Format (3.2, '5:1+')        returns ' 3.2+'
  930.                   Format (-3.2, '5:1+')       returns ' 3.2-'
  931.  
  932.  
  933.               The final  sign  option  allows negative  numbers  to  be
  934.           enclosed in parentheses and is specified with  a "P" in front
  935.           of the  size specifiers.  Positive numbers are formatted with
  936.           a trailing  space for  ease  of alignment.   (Note  that  all
  937.           alphabetic options in   the  format string may  be in  either
  938.           upper or lower case.)
  939.  
  940.                   Format (123.45, 'P10:2')    returns '   123.45 '
  941.                   Format (-678.9, 'P10:2')    returns '  (678.90)'
  942.  
  943.  
  944.               It is also possible  to display the  absolute value of  a
  945.           number by using the "A" option.  This causes negative numbers
  946.           to be converted to positive numbers before formatting.
  947.  
  948.                   Format (-68.4, 'A8:1')      returns '    68.4'
  949.                   Format (-68.4, '+A8:1')     returns '   +68.4'
  950.  
  951.  
  952.  
  953.  
  954.           
  955.           
  956.                                       -11-  
  957.           JUSTIFICATION AND FILL OPTIONS
  958.  
  959.               There are controls for  the justification of  the  number
  960.           and for  controlling  how  the  remainder  of  the  field  is
  961.           treated.  Each  of  these options is controlled by adding the
  962.           appropriate character to   the front of  the  format  string.
  963.           When several  options precede   the size specifiers they  may
  964.           appear in any order.
  965.  
  966.               Placing a "C" in  the  control  string causes numbers  of
  967.           1,000 or greater  (or -1,000   or  lower) to  have   embedded
  968.           commas.   This option may also be specified with a "," in the
  969.           format string.
  970.  
  971.                   Format (2000, '7')          returns '   2000'
  972.                   Format (2000, 'C7')         returns '  2,000'
  973.  
  974.  
  975.               It is also  possible to  have  values of zero   displayed
  976.           as  a blank field  by using  the "B"  option.   Any  non-zero
  977.           value  is formatted as per the   rest of the format   string.
  978.           Note that  the zero test is  performed on  the number   after
  979.           it  is rounded   for display.   This   means,  for   example,
  980.           that  a   value   of   0.005 formatted to  one decimal  place
  981.           would be considered to be zero and shown as a blank field.
  982.  
  983.               Format (100, 'B6:2')        returns '100.00'
  984.               Format (-0.002, 'B6:2')     returns '      '
  985.  
  986.  
  987.               It is sometimes  desirable to  ensure that  numbers  fill
  988.           the entire  width of    the field,  such   as  when  printing
  989.           checks.   Three options  allow the blanks within a  formatted
  990.           number to  be  filled.   If  the format  string  contains  an
  991.           asterisk the  left of  the field  is filled  with  asterisks.
  992.           These are placed before any leading  sign or currency symbol.
  993.  
  994.                   Format (-45, '*8:1')        returns '***-45.0'
  995.                   Format (12345, '*8:1')      returns '*12345.0'
  996.  
  997.           A similar  effect can  be achieved  by using  an "F"  in  the
  998.           control string, but  in this case  Format uses the  character
  999.           assigned to the Fill  field of FormatConfig.   This field  is
  1000.           initially set to an asterisk, giving the "*" and "F"  options
  1001.           the same meaning unless altered  by your program.  Note  that
  1002.           an assignment to FormatConfig.Fill has  no effect on the  "*"
  1003.           option.
  1004.  
  1005.               Placing a  "Z" in  the control  string causes a number to
  1006.           be printed  with leading zeros,  and these  are placed  after
  1007.           any  sign or  currency symbol.    Note  that the  "B"  option
  1008.           takes  precedence   over all  three fill   options   if   the
  1009.           rounded number is zero.
  1010.           
  1011.           
  1012.                                       -12-  
  1013.                   Format (2500, 'Z8:1')       returns '00002500'
  1014.                   Format (2500, '+Z8:1')      returns '+0002500'
  1015.                   Format (0.03, 'BZ8:1')      returns '        '
  1016.  
  1017.  
  1018.               A floating currency symbol can be placed in front of  the
  1019.           formatted amount by using  a dollar sign  ahead of the  field
  1020.           width in the control string.  When  combined with a sign, the
  1021.           symbol is  always placed  after a  plus, minus,   or  opening
  1022.           parenthesis.   It will also  always be placed after any  fill
  1023.           characters.
  1024.  
  1025.               Format (99.50, '$9:2')      returns '   $99.50'
  1026.               Format (-47.25, 'P$9:2')    returns ' ($47.25)'
  1027.               Format (1.25, 'P*$9:2')     returns '***$1.25 '
  1028.  
  1029.           The currency symbol can be changed to any other character  by
  1030.           an assignment to  the Currency field  of FormatConfig.   This
  1031.           would typically be done during your program's  initialization
  1032.           routine.  Note  that you  must still  use "$"  in the  string
  1033.           passed  to  Format;  only  the  resulting  character  in  the
  1034.           formatted string is  affected by the  assignment.   Assigning
  1035.           the null code  (#0) to FormatConfig.Currency  will cause  the
  1036.           "$" option to be ignored.
  1037.  
  1038.               Output from Format is normally right-justified, with  all
  1039.           leading positions either blank  or filled with the  specified
  1040.           fill character.  This  allows simple alignment when  printing
  1041.           figures in columns.  Use of the "L" option in a format string
  1042.           causes Format  to  left-justify  the  returned  string,  with
  1043.           trailing blanks to make up the correct field width.  The  "*"
  1044.           and "F" options may be used, in which case the specified fill
  1045.           character will pad the returned  number to the right.   Left-
  1046.           justification has  no  effect when  the  "Z" option  is  also
  1047.           selected, since the zeros  must be added to  the left of  the
  1048.           number.
  1049.  
  1050.  
  1051.           DISPLAY OF VULGAR FRACTIONS
  1052.  
  1053.               The final group of  formatting options allow the  display
  1054.           of numbers in vulgar fraction  form instead of decimal  form.
  1055.           The width specifier value should be followed by ":/" and then
  1056.           the value of denominator required.   For example, the  format
  1057.           string '12:/8' will  format numbers  to a field  width of  12
  1058.           characters, rounded to the nearest eighth.
  1059.  
  1060.                   Format (1.125, '12:/8')    returns '     1-1/8  '
  1061.                   Format (3.623, '12:/8')    returns '     3-5/8  '
  1062.  
  1063.           The maximum  allowable  value  for  the  denominator  is  99.
  1064.           Formatted output always allows  five character positions  for
  1065.           fractional part of the number,  plus one extra space for  the
  1066.           
  1067.           
  1068.                                       -13-  
  1069.           "-" separator.  This allows the integer part of the number to
  1070.           be easily aligned  when printing  numbers in columns.     The
  1071.           character used to separate the integral and fractional  parts
  1072.           of the number can be changed by an assignment to the  FracSep
  1073.           field of FormatConfig.
  1074.  
  1075.               Use of  vulgar fractions  automatically selects  the  "A"
  1076.           option to force absolute values and cancels any sign options.
  1077.           The "*" and "F" fill options may be used, and in addition  to
  1078.           their usual function will also  cause any space to the  right
  1079.           of  formatted  number  to   be  filled  with  the   specified
  1080.           character.  Zero-fill is not available with vulgar fractions,
  1081.           and a  "Z"  in  the  format  control  string  is  interpreted
  1082.           differently: Use of this option causes values of less than  1
  1083.           to be shown with a leading zero.
  1084.  
  1085.                   Format (0.25, '8:/4')    returns '   1/4  '
  1086.                   Format (0.25, 'Z8:/4')   returns ' 0-1/4  '
  1087.  
  1088.  
  1089.               The final option  affecting vulgar fractions  is the  "R"
  1090.           option to  disable fraction  reduction.   By default,  Format
  1091.           will reduce any fraction to the lowest possible form; use  of
  1092.           the "R" option  causes Format  to leave the  fraction in  the
  1093.           exact form specified, even if it could be reduced.
  1094.  
  1095.                   Format (0.5, '6:/8')    returns ' 1/2  '
  1096.                   Format (0.5, 'R6:/8')   returns ' 4/8  '
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.           
  1123.           
  1124.                                       -14-  
  1125.           CONTROL STRING SUMMARY
  1126.  
  1127.               [Options]  [Width] [:Decimals] [:/Fraction]  [Options]
  1128.  
  1129.  
  1130.           Width defaults to  12 characters if  not specified.  Decimals
  1131.           defaults to zero if not specified. Fraction may be any  value
  1132.           in the range 2 through 99.  Leading options may be placed  in
  1133.           any order; upper and lower case are equivalent.
  1134.  
  1135.  
  1136.           Trailing options:
  1137.  
  1138.                   +       Always add trailing plus or minus sign
  1139.                   -       Add trailing minus if negative
  1140.  
  1141.  
  1142.           Leading options:
  1143.  
  1144.                   +       Always add leading plus or minus sign
  1145.                   -       Add leading minus if negative (default)
  1146.                   P       Format negative numbers in parentheses
  1147.                   A       Show absolute value of supplied number
  1148.                   C ,     Add commas for thousands
  1149.                   B       Return blank field if result is zero
  1150.                   *       Pad field with asterisks
  1151.                   F       Pad field with user-defined character
  1152.                   Z       Zero-fill or add zero before vulgar fraction
  1153.                   $       Add floating currency symbol
  1154.                   L       Left-justify formatted number
  1155.                   R       Do not reduce vulgar fractions
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.           
  1179.           
  1180.                                       -15-  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.  
  1193.  
  1194.  
  1195.  
  1196.  
  1197.  
  1198.  
  1199.  
  1200.  
  1201.  
  1202.  
  1203.  
  1204.  
  1205.  
  1206.  
  1207.  
  1208.  
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.           
  1235.           
  1236.                                       -16-  
  1237.                                         3.
  1238.                                 UNIT MATH & MATH87 
  1239.           =============================================================
  1240.  
  1241.               Conversion  between  various  units  of  measurement   is
  1242.           required in a great many application programs.  The MATH  and
  1243.           MATH87 units  provide  a  wide range  of  functions  for  the
  1244.           conversion  of  linear,   square,  and  cubic   measurements,
  1245.           temperatures, weights, and so on.
  1246.  
  1247.               All the routines  require the  passing of  floating-point
  1248.           numbers, and to provide best versatility the units allow  you
  1249.           to  use  regular  REAL  numbers  or  EXTENDED  floating-point
  1250.           numbers.   The  latter use  the  8087 co-processor  or  Turbo
  1251.           Pascal's emulation (see your  reference manual for  details).
  1252.           If you wish  to use  regular REAL numbers,  declare the  MATH
  1253.           unit in  your  program's  USES  statement;  to  use  EXTENDED
  1254.           floating-point variables,  declare  the MATH87  unit.    Both
  1255.           units define a new variable type,  FLOAT, which is set to  be
  1256.           equivalent to type REAL or type EXTENDED, respectively.
  1257.  
  1258.               In programs which make extensive use of measurements,  it
  1259.           is recommended that the FLOAT type variable is always used to
  1260.           hold these measurements  in their  basic form  of inches  for
  1261.           linear measurement, square inches for area, and cubic  inches
  1262.           for volume.  It is then  easy to perform calculations on  the
  1263.           variables without having to always check whether the units of
  1264.           measurement are  the  same.    You  can  use  the  conversion
  1265.           routines described below when input and ouptut is required in
  1266.           feet, miles, square  yards, and so  on.  The  basic unit  for
  1267.           liquid measure is assumed to be the fluid ounce and the basic
  1268.           unit for weight is assumed to be the ounce.
  1269.  
  1270.               Metric conversions are also  included in the  MATH/MATH87
  1271.           unit.  The basic measurement units are taken to be the meter,
  1272.           square meter, cubic meter, and  gram.  Metric prefixes,  such
  1273.           as for centimeters, square  kilometers, kilograms, and so  on
  1274.           are easily derived from these basic forms.
  1275.  
  1276.           -------------------------------------------------------------
  1277.  
  1278.           FUNCTION FahrToCent (FahrTemp: FLOAT): FLOAT; 
  1279.           FUNCTION CentToFahr (CentTemp: FLOAT): FLOAT; 
  1280.           FUNCTION KelvToCent (KelvTemp: FLOAT): FLOAT; 
  1281.           FUNCTION CentToKelv (CentTemp: FLOAT): FLOAT; 
  1282.  
  1283.               These  four  functions  provide  temperature  conversions
  1284.           between Fahrenheit, Centigrade, and Kelvin measurements.  The
  1285.           supplied temperature is converted as required and returned by
  1286.           the function.   For  example, FahrToCent  takes a  Fahrenheit
  1287.           temperature passed  in  parameter FahrTemp  and  returns  the
  1288.           Centigrade equivalent.
  1289.  
  1290.           
  1291.           
  1292.                                       -17-  
  1293.               Direct conversions between Fahrenheit  and Kelvin can  be
  1294.           made by  using  the  return  value of  one  function  as  the
  1295.           parameter to another.  For example:
  1296.  
  1297.                   K := CentToKelv(FahrToCent(F));
  1298.  
  1299.           will convert  the  Fahrenheit  temperature F  to  its  Kelvin
  1300.           equivalent K.
  1301.  
  1302.               Note  that  no  error  checking  is  performed  by  these
  1303.           functions; it is left entirely to your own program to  ensure
  1304.           that valid values  (i.e. above absolute  zero) are passed  to
  1305.           the functions.
  1306.  
  1307.           -------------------------------------------------------------
  1308.  
  1309.           PROCEDURE InchToFtIn (Inches: FLOAT; VAR ft, ins: FLOAT); 
  1310.           FUNCTION  FtInToInch (ft, ins: FLOAT): FLOAT; 
  1311.  
  1312.               The FLOAT type variable, whether defined as type REAL  or
  1313.           type  EXTENDED,   has  adequate   capacity  to   allow   most
  1314.           measurements  to  be  stored   directly  in  inches.     Some
  1315.           applications, however, are easier to use if input and  output
  1316.           is separated into feet and inches; these two routines provide
  1317.           this conversion.
  1318.  
  1319.               InchToFtIn takes  the  measurement  passed  as  parameter
  1320.           Inches and  separates  it  into feet  and  inches  which  are
  1321.           returned in parameters  ft and  ins respectively.   An  input
  1322.           value of 61, for example, will cause values of 5 and 1 to  be
  1323.           returned.
  1324.  
  1325.               FtInToInch performs  the converse  function and  combines
  1326.           the two supplied parameters to return a single measurement in
  1327.           inches.  Note that it is  quite permissible for ins to be  12
  1328.           or greater.  For  example, if ft  is passed as  3 and ins  is
  1329.           passed as 25, then the function will return a value of 61.
  1330.  
  1331.           -------------------------------------------------------------
  1332.  
  1333.           FUNCTION InchToYard (Inches: FLOAT): FLOAT; 
  1334.           FUNCTION YardToInch (Yards: FLOAT): FLOAT; 
  1335.  
  1336.               These two  functions  provide direct  conversion  between
  1337.           inches and  yards,  for  situations  where  measurements  are
  1338.           stored in inches but input or output must be in yards.
  1339.  
  1340.               InchToYard  takes  the  supplied  parameter  Inches   and
  1341.           returns a value that represents  the same distance in  yards.
  1342.           YardToInch  takes  the  parameter   Yards  and  returns   the
  1343.           equivalent measurement in inches.
  1344.  
  1345.               Note  that  negative  values  are  permissible  with  all
  1346.           
  1347.           
  1348.                                       -18-  
  1349.           conversion functions such as  these; the returned value  will
  1350.           simply reflect the sign of the supplied parameter.
  1351.  
  1352.           -------------------------------------------------------------
  1353.  
  1354.           FUNCTION InchToMile (Inches: FLOAT): FLOAT; 
  1355.           FUNCTION MileToInch (Miles: FLOAT): FLOAT; 
  1356.           FUNCTION InchToNautMile (Inches: FLOAT): FLOAT; 
  1357.           FUNCTION NautMileToInch (NautMiles: FLOAT): FLOAT; 
  1358.  
  1359.               Four functions provide  direct conversion between  inches
  1360.           and  miles.  InchToMile  and  MileToInch  take  the  supplied
  1361.           parameter and convert it using  the standard statute mile  of
  1362.           5,280  feet.    InchToNautMile  and  NautMileToInch   provide
  1363.           similar conversions based on the nautical mile of 6,080 feet.
  1364.  
  1365.           -------------------------------------------------------------
  1366.  
  1367.           FUNCTION InchToMeter (Inches: FLOAT): FLOAT; 
  1368.           FUNCTION MeterToInch (Meters: FLOAT): FLOAT; 
  1369.  
  1370.               These functions  provide conversion  between English  and
  1371.           metric linear measurements.  InchToMeter takes the  parameter
  1372.           supplied in Inches  and returns a  value that represents  the
  1373.           metric  equivalent  in  meters.    MeterToInch  performs  the
  1374.           reverse function.
  1375.  
  1376.           -------------------------------------------------------------
  1377.  
  1378.           FUNCTION SqInchToSqFeet (SqInches: FLOAT): FLOAT; 
  1379.           FUNCTION SqFeetToSqInch (SqFeet: FLOAT): FLOAT; 
  1380.           FUNCTION SqInchToSqYard (SqInches: FLOAT): FLOAT; 
  1381.           FUNCTION SqYardToSqInch (SqYards: FLOAT): FLOAT; 
  1382.           FUNCTION SqInchToSqMile (SqInches: FLOAT): FLOAT; 
  1383.           FUNCTION SqMileToSqInch (SqMiles: FLOAT): FLOAT; 
  1384.           FUNCTION SqInchToAcre (SqInches: FLOAT): : FLOAT; 
  1385.           FUNCTION AcreToSqInch (Acres: FLOAT): FLOAT; 
  1386.  
  1387.               This group of functions provides conversion between units
  1388.           for measurements of area.  Each function takes a  measurement
  1389.           in square  inches and  returns the  equivalent value  in  the
  1390.           specified unit  of measurement,  or takes  the value  in  the
  1391.           specified unit and returns  the equivalent in square  inches.
  1392.           The square  mile used  in  this conversion  is based  on  the
  1393.           statute mile of 5,280 feet.
  1394.  
  1395.           -------------------------------------------------------------
  1396.  
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402.           
  1403.           
  1404.                                       -19-  
  1405.           FUNCTION SqInchToSqMeter (SqInches: FLOAT): FLOAT; 
  1406.           FUNCTION SqMeterToSqInch (SqMeters: FLOAT): FLOAT; 
  1407.  
  1408.               SqInchToSqMeter and SqMeterToSqInch provide conversion of
  1409.           area measurements between  English and metric  units.   Other
  1410.           metric  units   of  square   measurement,  such   as   square
  1411.           centimeters or square kilometers  can be easily derived  from
  1412.           the square-meters value.
  1413.  
  1414.           -------------------------------------------------------------
  1415.  
  1416.           FUNCTION CuInchToCuFeet (CuInches: FLOAT): FLOAT; 
  1417.           FUNCTION CuFeetToCuInch (CuFeet: FLOAT): FLOAT; 
  1418.           FUNCTION CuInchToCuYard (CuInches: FLOAT): FLOAT; 
  1419.           FUNCTION CuYardToCuInch (CuYards: FLOAT): FLOAT; 
  1420.  
  1421.               These four  functions provide  conversions between  cubic
  1422.           inches, cubic  feet,  and  cubic yards  for  measurements  of
  1423.           volume.  The parameter passed to the function is converted to
  1424.           the required value and returned to the calling program.
  1425.  
  1426.           -------------------------------------------------------------
  1427.  
  1428.           FUNCTION CuInchToCuMeter (CuInches: FLOAT): FLOAT; 
  1429.           FUNCTION CuMeterToCuInch (CuMeters: FLOAT): FLOAT; 
  1430.  
  1431.               CuInchToCuMeter allows volumes given in English units  to
  1432.           be converted  to their  metric equivalent.    CuMeterToCuInch
  1433.           performs the converse function.
  1434.  
  1435.           -------------------------------------------------------------
  1436.  
  1437.           FUNCTION FluidOzToPint (FluidOz: FLOAT): FLOAT; 
  1438.           FUNCTION PintToFluidOz (Pints: FLOAT): FLOAT; 
  1439.           FUNCTION FluidOzToGals (FluidOz: FLOAT): FLOAT; 
  1440.           FUNCTION GalsToFluidOz (Gals: FLOAT): FLOAT; 
  1441.           FUNCTION FluidOzToImpPint (FluidOz: FLOAT): FLOAT; 
  1442.           FUNCTION ImpPintToFluidOz (ImpPints: FLOAT): FLOAT; 
  1443.           FUNCTION FluidOzToImpGals (FluidOz: FLOAT): FLOAT; 
  1444.           FUNCTION ImpGalsToFluidOz (ImpGals: FLOAT): FLOAT; 
  1445.  
  1446.               For liquid volume  measurements, these functions  provide
  1447.           conversion between fluid ounces, pints, and gallons.
  1448.  
  1449.               The first  four  functions  are  based  on  the  standard
  1450.           American system of 16 fluid  ounces per pint.  The  remaining
  1451.           functions use the Imperial system  of measurement in which  a
  1452.           pint consists of 20 fluid ounces; this system is used in most
  1453.           English-speaking countries that were once part of the British
  1454.           Commonwealth, such as Australia and New Zealand.
  1455.  
  1456.           -------------------------------------------------------------
  1457.  
  1458.           
  1459.           
  1460.                                       -20-  
  1461.           FUNCTION FluidOzToCuMeter (FluidOz: FLOAT): FLOAT; 
  1462.           FUNCTION CuMetersToFluidOz (CuMeters: FLOAT): FLOAT; 
  1463.  
  1464.               These two functions convert between fluid ounces and  the
  1465.           metric system of liquid  measurement.  Cubic centimeters  and
  1466.           liters can be derived from cubic meters.
  1467.  
  1468.           -------------------------------------------------------------
  1469.  
  1470.           PROCEDURE OunceToLbOz (Ounces: FLOAT; VAR lb, oz: FLOAT); 
  1471.           FUNCTION  LbOzToOunce (lb, oz: FLOAT): FLOAT; 
  1472.  
  1473.               For applications where it is  required to enter or  print
  1474.           weights as  pounds and  ounces,  these two  routines  provide
  1475.           conversion to or from the total number of ounces.
  1476.  
  1477.               OunceToLbOz takes the value passed in Ounces and  returns
  1478.           the equivalent  weight as  pounds  and ounces  in lb  and  oz
  1479.           respectively.   LbOzToOunce takes  separate pound  and  ounce
  1480.           measurements and returns  a value that  represents the  total
  1481.           weight in  ounces.   Note that  the function  will  correctly
  1482.           handle a value of oz that exceeds 16.
  1483.  
  1484.           -------------------------------------------------------------
  1485.  
  1486.           FUNCTION OunceToTon (Ounces: FLOAT): FLOAT; 
  1487.           FUNCTION TonToOunce (Tons: FLOAT): FLOAT; 
  1488.           FUNCTION OunceToLongTon (Ounces: FLOAT): FLOAT; 
  1489.           FUNCTION LongTonToOunce (LongTons: FLOAT): FLOAT; 
  1490.  
  1491.               The first  two  of  these  functions  provide  conversion
  1492.           between ounces and the standard American ton of 2,000 pounds.
  1493.           (This is  also  known  as  a short  ton.)    The  second  two
  1494.           functions convert between  ounces and the  long ton of  2,240
  1495.           pounds.    This  is  the  "standard"  ton  in  most   British
  1496.           Commonwealth countries.
  1497.  
  1498.           -------------------------------------------------------------
  1499.  
  1500.           FUNCTION OunceToGram (Ounces: FLOAT): FLOAT; 
  1501.           FUNCTION GramToOunce (Grams: FLOAT): FLOAT; 
  1502.  
  1503.               OunceToGram and  GramToOunce provide  conversion  between
  1504.           the basic measurements  of weight in  the English and  metric
  1505.           systems.  Other  metric derivatives, such  as kilograms,  are
  1506.           easily obtained from the basic gram.
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513.  
  1514.           
  1515.           
  1516.                                       -21-  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523.  
  1524.  
  1525.  
  1526.  
  1527.  
  1528.  
  1529.  
  1530.  
  1531.  
  1532.  
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.           
  1571.           
  1572.                                       -22-  
  1573.                                         4.
  1574.                                     UNIT TIME 
  1575.           =============================================================
  1576.  
  1577.               Many programs require the use of dates and times in  some
  1578.           form.    Such programs  range   from  simple  disk  utilities
  1579.           to full accounting systems.
  1580.  
  1581.               Turbo Pascal's own date and time functions are limited to
  1582.           the setting or retrieving of   the system clock and the  date
  1583.           and time  of a  disk   file.   This unit  provides many  more
  1584.           routines which will  be found useful  for the input,  output,
  1585.           and manipulation of dates and times.
  1586.  
  1587.  
  1588.           GLOBAL DECLARATIONS
  1589.  
  1590.               The unit defines four new types:
  1591.  
  1592.                   DateString      = STRING[9];
  1593.                   TimeString      = STRING[13];
  1594.  
  1595.                   DateRec         = RECORD
  1596.                                           M, D:   BYTE;
  1597.                                           Y:      WORD;
  1598.                                     END;
  1599.  
  1600.                   TimeRec         =  RECORD
  1601.                                           H, M, S:  BYTE;
  1602.                                      END;
  1603.  
  1604.  
  1605.               The first two definitions are used to return strings from
  1606.           the unit's functions.   The second  two provide a  convenient
  1607.           way to  store  a  date  or  time  in  a  single,  three-field
  1608.           variable.  The M,  D, and Y fields  of type DateRec hold  the
  1609.           month, day, and year, respectively.  Note that the field  for
  1610.           the year is defined as type word and the  unit always expects
  1611.           the year  to  be  specified  in full  (e.g.  1990  should  be
  1612.           assigned as 1990, not just 90).    The H, M, and S fields  of
  1613.           type TimeRec are used to hold the hours, minutes, and seconds
  1614.           of a time, respectively.
  1615.  
  1616.               The following  constants  and typed  constants  are  also
  1617.           defined in  the  interface  of  the unit.      Their  use  is
  1618.           described with  each routine when necessary.
  1619.  
  1620.                   DateFormNumeric       = 0;
  1621.                   DateFormAlpha         = 1;
  1622.                   DateFormMDY           = 2;
  1623.                   DateFormDMY           = 3;
  1624.                   DateFormLower         = 4;
  1625.                   DateFormZeroFill      = 8;
  1626.           
  1627.           
  1628.                                       -23-  
  1629.                   FullDateFormMDY       = 0;
  1630.                   FullDateFormDMY       = 1;
  1631.  
  1632.                   TimeFormNormal        = 0;
  1633.                   TimeFormNormalSec     = 1;
  1634.                   TimeFormShort         = 2;
  1635.                   TimeFormShortSec      = 3;
  1636.                   TimeFormMilitary      = 4;
  1637.                   TimeFormMilitarySec   = 5;
  1638.                   TimeFormMilitaryHHMM  = 6;
  1639.  
  1640.                   TimeFormat:       BYTE    = TimeFormNormal;
  1641.                   DateFormat:       BYTE    = DateFormNumeric;
  1642.                   FullDateFormat:   BYTE    = FullDateFormMDY;
  1643.  
  1644.                   TimeDelimiter:    CHAR    = ':';
  1645.                   DateDelimiter:    CHAR    = '/';
  1646.  
  1647.                   TimeParseDelims:  TimeString  = ':., ' + #9;
  1648.                   DateParseDelims:  DateString = '/-., ' + #9;
  1649.  
  1650.                   TimeParseNow:     BOOLEAN = FALSE;
  1651.                   DateParseToDay:   BOOLEAN = FALSE;
  1652.                   DateParseCurYear: BOOLEAN = FALSE;
  1653.                   DateParseCent21:  BYTE    = 0;
  1654.  
  1655.           -------------------------------------------------------------
  1656.  
  1657.           PROCEDURE CombineDateTime (VAR DtTm: DateTime;
  1658.                                          Dt:   DateRec;
  1659.                                          Tm:   TimeRec);
  1660.  
  1661.           PROCEDURE SplitDateTime   (DtTm:   DateTime;
  1662.                                      VAR Dt: DateRec;
  1663.                                      VAR Tm: TimeRec);
  1664.  
  1665.               The  DOS  unit  supplied  with  Turbo  Pascal  defines  a
  1666.           DateTime type which can be used in conjunction with the  file
  1667.           date and time routines.  These two procedures provide a means
  1668.           for combining  separate  date  and time  variables  into  one
  1669.           common record  and for  splitting  the combined  record  into
  1670.           separate date and time records.
  1671.  
  1672.               CombineDateTime takes the  supplied date and  time in  Dt
  1673.           and Tm and returns the variable DtTm with all six fields set.
  1674.           SplitDateTime takes the values  supplied in DtTm and  returns
  1675.           with  Dt  and  Tm  set   to  the  specified  date  and   time
  1676.           respectively.
  1677.  
  1678.               Note that no error checking is performed for out of range
  1679.           values.  Since the fields of the DateTime type are defined as
  1680.           being of type WORD, then any data in the high-order byte will
  1681.           be lost when passed to SplitDateTime.
  1682.           
  1683.           
  1684.                                       -24-  
  1685.           -------------------------------------------------------------
  1686.  
  1687.           PROCEDURE GetToDay (VAR Dt: DateRec);
  1688.  
  1689.               GetToDay simply returns  the current system  date in  the
  1690.           record Dt.  If, for example, the system date was December 15,
  1691.           1990, then Dt would have its three fields, M, D,  and Y,  set
  1692.           to 12, 15,  and 1990 respectively.
  1693.  
  1694.           -------------------------------------------------------------
  1695.           PROCEDURE GetTimeNow (VAR Tm: TimeRec);
  1696.  
  1697.               This procedure sets  the   three fields  of   Tm the  the
  1698.           current system  time.     All   the time-handling    routines
  1699.           assume that the hours field, H, holds a value of 0 (midnight)
  1700.           through 23  (11 p.m.).  The minutes and seconds fields, M and
  1701.           S, may hold a value of up to 59.
  1702.  
  1703.           -------------------------------------------------------------
  1704.  
  1705.           PROCEDURE GetDateTime (VAR DtTm: DateTime);
  1706.  
  1707.               This procedure allows  the current  date and  time to  be
  1708.           obtained from the system clock with a single subroutine call.
  1709.           The six fields  of DtTm  are set  to the  current values  for
  1710.           year, month, day, hours, minutes, and seconds.
  1711.  
  1712.           -------------------------------------------------------------
  1713.  
  1714.           FUNCTION DateValid (Dt: DateRec): BOOLEAN;
  1715.  
  1716.               DateValid examines   the   three   fields   within    the
  1717.           supplied parameter Dt and returns  true if they form a  valid
  1718.           date.
  1719.  
  1720.               Only dates in the range  January 1, 1900 through June  6,
  1721.           2079 are accepted  as valid  (i.e.  the range  of  dates that
  1722.           can  be represented as a  two-byte word).   The month  field,
  1723.           M, must be  1  through 12, and the day  field, D,  must be  1
  1724.           through 28, 29,  30, or 31 as  appropriate to  the month.   A
  1725.           date of February 29   will only be  accepted as valid if  the
  1726.           year field also specifies a leap year.
  1727.  
  1728.           -------------------------------------------------------------
  1729.  
  1730.           FUNCTION TimeValid (Tm: TimeRec): BOOLEAN;
  1731.  
  1732.               TimeValid checks the three fields  of the variable passed
  1733.           as parameter Tm and returns true  if they form a valid  time.
  1734.           If  the time in Tm is in any way invalid (minutes or  seconds
  1735.           greater than 59 or hours greater than 23)  then the  function
  1736.           returns a  result of false.
  1737.  
  1738.           
  1739.           
  1740.                                       -25-  
  1741.           -------------------------------------------------------------
  1742.  
  1743.           FUNCTION DateTimeValid (DtTm: DateTime);
  1744.  
  1745.               DateTimeValid combines the actions  of the DateValid  and
  1746.           TimeValid  functions,  allowing  a   validity  check  to   be
  1747.           performed on a variable of type DateTime.  If the  high-order
  1748.           byte of any supplied field is not zero, the function  returns
  1749.           false,  otherwise  the  date  and  time  are  passed  to  the
  1750.           DateValid and TimeValid functions for  checking.  A value  of
  1751.           true will be  returned only  if both  the date  and time  are
  1752.           valid.
  1753.  
  1754.           -------------------------------------------------------------
  1755.  
  1756.           PROCEDURE WordToDate (w: WORD; VAR Dt: DateRec);
  1757.  
  1758.               WordToDate  performs    the   opposite    conversion   to
  1759.           DateToWord. The date represented by  the value supplied in  w
  1760.           is converted to a three-field date in parameter Dt.
  1761.  
  1762.           -------------------------------------------------------------
  1763.  
  1764.           FUNCTION DateToWord (Dt: DateRec): WORD;
  1765.  
  1766.               This function allows  a date in  the form of  a record to
  1767.           be converted to  a  simple   integer.    DateToWord   assumes
  1768.           that  0 represents January  1, 1900, 1 represents January  2,
  1769.           1900, and   so  on.   The  two-byte  value   can,  therefore,
  1770.           represent any date  from January 1, 1900 to June 6, 2079.
  1771.  
  1772.               There are two advantages to  representing a date in  this
  1773.           way. First, storage requirements are reduced  when many dates
  1774.           must  be handled because a variable of  type DateRec requires
  1775.           four  bytes. Second,  it is easy  to perform calculations  by
  1776.           simple addition and subtraction.  To do  this with a variable
  1777.           of type  DateRec   would require  careful consideration  with
  1778.           regard to month  end, year  end, and  leap years.   The  word
  1779.           representation of the date accounts for all 28-, 29-, 30-, or
  1780.           31-day months (e.g.  33,052 is  June 30, 1990  and 33,053  is
  1781.           July 1, 1990).
  1782.  
  1783.               Note that   no  error   checking is   performed  on   the
  1784.           supplied date.   If  the date  in  parameter Dt  is   invalid
  1785.           in  some  way  DateToWord will still return  a  value but  it
  1786.           will represent  some other date entirely.
  1787.  
  1788.           -------------------------------------------------------------
  1789.  
  1790.  
  1791.  
  1792.  
  1793.  
  1794.           
  1795.           
  1796.                                       -26-  
  1797.           FUNCTION LeapYear (Y: WORD): BOOLEAN;
  1798.  
  1799.               This function checks  the year  supplied as  parameter  Y
  1800.           and returns true if it is a leap year or false if it is  not.
  1801.           As with the other date functions, Y must  specify the year in
  1802.           full  (e.g. 1990 must be passed as 1990, not 90).
  1803.  
  1804.           -------------------------------------------------------------
  1805.  
  1806.           FUNCTION TimeAP (Tm: TimeRec): TimeString;
  1807.  
  1808.               This function  simply  returns  a  four-character  string
  1809.           of 'a.m.' if the time in Tm  is before noon or 'p.m.' if  the
  1810.           time  in Tm is after noon.
  1811.  
  1812.           -------------------------------------------------------------
  1813.  
  1814.           PROCEDURE AdjustDate (VAR Dt: DateRec; n: INTEGER);
  1815.  
  1816.               In order to   add or subtract   a given  number  of  days
  1817.           from   a date  specified as   a  variable   of type  DateRec,
  1818.           three steps  are necessary.     First,  the   date  must   be
  1819.           converted  using   the DateToWord  function.    Second,   the
  1820.           number  of  days  adjustment required is  added  or deducted.
  1821.           Third, the  integer  must  be converted back to a three-field
  1822.           record using WordToDate.
  1823.  
  1824.               This procedure  combines  these   three  steps  into  one
  1825.           routine, making  such  adjustments  simpler  in    your  main
  1826.           program.  The  date variable to be adjusted should be  passed
  1827.           as Dt and  the number   of  days adjustment,  plus or  minus,
  1828.           should be passed a parameter n.
  1829.  
  1830.               Note that  no range  checking is  performed on  the date,
  1831.           so trying to adjust to before  January 1, 1900 or after  June
  1832.           6,  2079 will produce undesired  results.   Given the   range
  1833.           of dates   that this unit  can handle, this  should not be  a
  1834.           problem in most applications.
  1835.  
  1836.           -------------------------------------------------------------
  1837.  
  1838.           PROCEDURE AdjustTime (VAR Tm: TimeRec; n: LongInt);
  1839.  
  1840.               AdjustTime takes the time passed in Tm and adjusts it  by
  1841.           the number of seconds passed in parameter n.  Positive values
  1842.           adjust the  time forward;  negative  values adjust  the  time
  1843.           backward.
  1844.  
  1845.               Note that no indication is given if the adjustment causes
  1846.           the time to pass midnight in  either direction.  If you  must
  1847.           account  for  the  date  as   well  as  the  time,  use   the
  1848.           AdjustDateTime function.
  1849.  
  1850.           
  1851.           
  1852.                                       -27-  
  1853.           -------------------------------------------------------------
  1854.  
  1855.           PROCEDURE AdjustDateTime (VAR DtTm: DateTime; n: LongInt);
  1856.  
  1857.               This routine works  in a similar  way to AdjustTime,  but
  1858.           also  provides  for  adjustment  of  the  date  if  the  time
  1859.           adjustment causes midnight to be passed in either  direction.
  1860.           The date and time  are returned in  DtTm after the  necessary
  1861.           alteration has been made.
  1862.  
  1863.               Note that no range  checking is performed  on any of  the
  1864.           fields, so invalid dates and times supplied to AdjustDateTime
  1865.           will give meaningless  results.  The  date range  limitations
  1866.           listed under AdjustDate also apply.
  1867.  
  1868.           -------------------------------------------------------------
  1869.  
  1870.           PROCEDURE SetLastDay (VAR Dt: DateRec);
  1871.  
  1872.               SetLastDay will  be  found   useful  in  many  accounting
  1873.           programs which require an end-of-month date.
  1874.  
  1875.               The month  and year  fields of  the date  variable passed
  1876.           as parameter Dt should be set to the required month.  The day
  1877.           field, may  have any  value  upon entry.     SetLastDay  will
  1878.           return with  the month and  year fields unchanged,  but  will
  1879.           have adjusted the  day field to the last day of the specified
  1880.           month.   (The year  field is  required only  for  determining
  1881.           whether February should have 28  or 29 days.)
  1882.  
  1883.           -------------------------------------------------------------
  1884.  
  1885.           FUNCTION DayOfWeek (w: WORD): BYTE;
  1886.  
  1887.               This function should be passed  a date value as parameter
  1888.           w. The value   must  be   in  the   form  provided   by   the
  1889.           DateToWord function.
  1890.  
  1891.               DayOfWeek returns a  number that  represents the  day  of
  1892.           the week for the specified date.  Only a value of 0 through 6
  1893.           will be returned:
  1894.  
  1895.                                   0  =  Sunday
  1896.                                   1  =  Monday
  1897.                                   2  =  Tuesday
  1898.                                   3  =  Wednesday
  1899.                                   4  =  Thursday
  1900.                                   5  =  Friday
  1901.                                   6  =  Saturday
  1902.  
  1903.           -------------------------------------------------------------
  1904.  
  1905.  
  1906.           
  1907.           
  1908.                                       -28-  
  1909.           FUNCTION DayOfWeekStr (d: BYTE): DateString;
  1910.  
  1911.               This   function    converts   the    day-of-week    value
  1912.           (described above) to a string containing the name of the day.
  1913.           The  returned  string is variable  in length,   to match  the
  1914.           number of  characters in the name, and each name is in  mixed
  1915.           case.
  1916.  
  1917.               If the value supplied in parameter  d is greater than  6,
  1918.           the function returns a null string.
  1919.  
  1920.           -------------------------------------------------------------
  1921.  
  1922.           FUNCTION MonthStr (M: BYTE): DateString;
  1923.  
  1924.               This function    works  in    a similar    way  to    the
  1925.           DayOfWeekStr function and returns the  name of  a month  when
  1926.           given its  number. The returned string is variable in length,
  1927.           to match the number  of characters in the  full  name of  the
  1928.           month,  and the names are  in mixed case.
  1929.  
  1930.               If the   supplied   parameter is   out   of  range,   the
  1931.           function returns a null string.
  1932.  
  1933.           -------------------------------------------------------------
  1934.  
  1935.           FUNCTION DayOfMonthStr (D: BYTE): DateString;
  1936.  
  1937.               This function returns a  three- or four-character  string
  1938.           based upon  the value  passed  in parameter  D.   The  string
  1939.           consists of the  number followed by   the appropriate  suffix
  1940.           (i.e. 1st, 2nd,  3rd, 4th, etc.).
  1941.  
  1942.               If D is out of range, a null string is returned.
  1943.  
  1944.           -------------------------------------------------------------
  1945.  
  1946.           FUNCTION DateStr (Dt: DateRec): DateString;
  1947.  
  1948.               DateStr takes a date in  the parameter Dt and formats  it
  1949.           into a string suitable for display or printing.
  1950.  
  1951.               There are  two basic  formats for  the string  -  numeric
  1952.           and alphanumeric.   The    default setting  is   numeric  and
  1953.           DateStr  will return  a string  of  eight  characters in  the
  1954.           form 'mm/dd/yy'   or  'dd-mm-yy'  depending on  whether  your
  1955.           system configuration is   set to  American or British  format
  1956.           with a COUNTRY line in CONFIG.SYS.   For example, a  date  of
  1957.           December  15,  1990   will  be   returned  as '12/15/90'   or
  1958.           '15-12-90'.    Note  that  the  year  appears  in abbreviated
  1959.           form as just the last two digits.
  1960.  
  1961.  
  1962.           
  1963.           
  1964.                                       -29-  
  1965.               The delimiter separating the month, day, and year may  be
  1966.           changed by  assigning  a  character to  the  global  variable
  1967.           DateDelimiter.  Assigning '.' to DateDelimiter, for  example,
  1968.           would cause future calls to  DateStr to return '12.15.90'  or
  1969.           '15.12.90'  as  appropriate.    The  character  assigned   to
  1970.           DateDelimiter may  be changed  at  any time;  the  assignment
  1971.           stays in effect until another  assignment to the variable  is
  1972.           made.  The unit initializes the delimiter to a "/" or "-" for
  1973.           American and  British formats  respectively.   Note that  the
  1974.           country setting for  DateStr is determined  at run-time,  not
  1975.           compile-time, so any  program using DateStr  will always  use
  1976.           the current country setting.
  1977.  
  1978.               Another global variable, DateFormat, is used to determine
  1979.           the way in which DateStr builds  the string it returns.   The
  1980.           values used are listed in the introduction to this unit.
  1981.  
  1982.               DateFormat is  initialized  to  DateFormNumeric,  causing
  1983.           DateStr to  return  a string  of  the form  described  above.
  1984.           Assigning DateFormMDY will cause  DateStr to always return  a
  1985.           date in American format, even if the system configuration  is
  1986.           set to British date format.  Similarly, assigning DateFormDMY
  1987.           will cause DateStr to always return a date in British format,
  1988.           regardless  of   the   country  setting   in   the   system's
  1989.           configuration file.
  1990.  
  1991.               Setting DateFormat  to  the constant  DateFormAlpha  will
  1992.           cause further  calls to  DateStr to  return a  nine-character
  1993.           string of the form 'dd/mmm/yy'  or 'dd-mmm-yy'.  The date  of
  1994.           December  15,  1990  shown  above,  for  example,  might   be
  1995.           formatted as '15-DEC-90'. (The  separators would be  replaced
  1996.           with  whatever  character,  if  any,  had  been  assigned  to
  1997.           DateDelimiter.)
  1998.  
  1999.               Two further options may be  used in conjunction with  the
  2000.           numeric   and    alphanumeric    formats.       The    values
  2001.           DateFormZeroFill and DateFormLower may be added to any of the
  2002.           other values.   The  former  causes a  leading blank  in  the
  2003.           string to be  replaced by  a zero.   For example,  a date  of
  2004.           January 1, 1991  would be returned  as '01/01/91' instead  of
  2005.           ' 1/01/91'.  Note  that without the  zero-fill option  single
  2006.           digit numbers  start with  a space.   This  is done  to  ease
  2007.           alignment of printed columns.   A similar result is  obtained
  2008.           by  adding  DateFormZeroFill  to  the  alphanumeric   format:
  2009.           ' 1-JAN-91' would be replaced with '01-JAN-91'.
  2010.  
  2011.               The second option is applicable only to the  alphanumeric
  2012.           format and causes  the month  abbreviation to  be printed  in
  2013.           mixed upper and lower case instead of all capitals.   DateStr
  2014.           would return '01-Jan-91' instead of '01-JAN-91'.
  2015.  
  2016.               A typical program  sets DateFormat and  DateDelimiter  to
  2017.           the required values once and then leaves them alone.
  2018.           
  2019.           
  2020.                                       -30-  
  2021.           -------------------------------------------------------------
  2022.  
  2023.           FUNCTION FullDateStr (Dt: DateRec): STRING;
  2024.  
  2025.               FullDateStr provides  a  similar   facility  to  that  of
  2026.           DateStr, but returns a longer  string containing the name  of
  2027.           the month  and the year in full.
  2028.  
  2029.               FullDateStr may   be  set   to format   a  date   in  two
  2030.           different ways.  The default  setting is 'month dd, yyyy';  a
  2031.           typical example of formatted output is 'January 2, 1991'.
  2032.  
  2033.               Just as the global variable DateFormat is used to control
  2034.           the way  in   which   DateStr   presents  its   output,    so
  2035.           FullDateFormat controls  the   way    in which    FullDateStr
  2036.           presents output.      The constant  FullDateFormMDY   selects
  2037.           the default  option  described above.  Assigning the constant
  2038.           FullDateFormDMY to  FullDateFormat causes all future calls to
  2039.           FullDateStr to  return a  string  of   the form  'ddxx  month
  2040.           yyyy', where "xx" represents the date suffix, as returned  by
  2041.           the DayOfMonthStr  function.  The   date shown in  the  above
  2042.           example would be formatted as '2nd January 1991'.
  2043.  
  2044.               Note that  the  settings of  DateFormat,   DateDelimiter,
  2045.           and country  selection  have  no effect  on  the  FullDateStr
  2046.           function.
  2047.  
  2048.           -------------------------------------------------------------
  2049.  
  2050.           FUNCTION TimeStr (Tm: TimeRec): TimeString;
  2051.  
  2052.               TimeStr converts the  time passed  as parameter  Tm to  a
  2053.           string suitable for printing or display.
  2054.  
  2055.               There are several ways in which the output of TimeStr may
  2056.           be formatted and these are determined by the value set in the
  2057.           global variable TimeFormat.   Several constants are  provided
  2058.           by the unit  to enable this setting to be made.
  2059.  
  2060.               The default  format, TimeFormNormal,  causes the  time to
  2061.           be formatted as   'hh:mm   x.m.', where   "x.m."   is  either
  2062.           "a.m."  or "p.m."  as  appropriate.    The  hours  field   is
  2063.           converted    to  conventional 12-hour   format   and  numbers
  2064.           less  than 10  have  a  leading space to  ease alignment   of
  2065.           columns.   Typical   returned strings would  be ' 2:35  p.m.'
  2066.           and '12:06 a.m.'.  Note that   the seconds field is  ignored.
  2067.           If  the  system  running  the  program  is  set  to   British
  2068.           configuration with  a COUNTRY  line in  CONFIG.SYS, then  the
  2069.           colon separator is replaced with a period, giving output such
  2070.           as ' 2.35 p.m.' and '12.06 a.m.'.
  2071.  
  2072.  
  2073.  
  2074.           
  2075.           
  2076.                                       -31-  
  2077.               The seconds field can be added to the formatted string by
  2078.           the assignment    of   the  constant    TimeFormNormalSec  to
  2079.           TimeFormat.      A   typical   returned   string   would   be
  2080.           ' 8:05:30 p.m.'.
  2081.  
  2082.               A shortened form  of the time  is available by  assigning
  2083.           TimeFormShort  or  TimeFortShortSec  to  TimeFormat.    These
  2084.           options are similar  to TimeFormNormal and  TimeFormNormalSec
  2085.           but omit the  "a.m." or "p.m."  indicator.  Typical  returned
  2086.           strings would be ' 8:05' and ' 8:05:30' respectively.
  2087.  
  2088.               Setting TimeFormat   to  the   constant  TimeFormMilitary
  2089.           causes TimeStr  to   return   a  string   in   military  time
  2090.           format  'hh:mm'.   If  the constant   TimeFormMilitarySec  is
  2091.           assigned  to    TimeFormat,  the  seconds  field  is   added.
  2092.           Examples of military format with and without seconds  display
  2093.           would be '20:05' and '20:05:30' respectively.
  2094.  
  2095.               The final  option,  TimeFormMilitaryHHMM, causes  TimeStr
  2096.           to return    a     four-character   string     without    the
  2097.           hours/minutes separator.  For example,   8:25 p.m. would   be
  2098.           returned as   '2025'  and  4:45 a.m.  would be  formatted  as
  2099.           '0445'.
  2100.  
  2101.               To clarify the way in which TimeStr works, the  following
  2102.           examples show the output for each format when the function is
  2103.           given the time 9:10:50 p.m.:
  2104.  
  2105.                   ' 9:10 p.m.'       (TimeFormNormal)
  2106.                   ' 9:10:50 p.m.'    (TimeFormNormalSec)
  2107.                   ' 9:10'            (TimeFormShort)
  2108.                   ' 9:10:50'         (TimeFormShortSec)
  2109.                   '21:10'            (TimeFormMilitary)
  2110.                   '21:10:50'         (TimeFormMilitarySec)
  2111.                   '2110'             (TimeFormMilitaryHHMM)
  2112.  
  2113.  
  2114.               One other    adjustment to    the formatted    output  is
  2115.           possible. The  separating colon  or  period can  be  replaced
  2116.           with another character  by making an assignment to the global
  2117.           variable TimeDelimiter.   This separator appears  between the
  2118.           hours and   minutes  fields   unless TimeFormMilitaryHHMM  is
  2119.           selected.   The separator  is also  used between minutes  and
  2120.           seconds  if the  selected  format  displays seconds.
  2121.  
  2122.           -------------------------------------------------------------
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128.  
  2129.  
  2130.           
  2131.           
  2132.                                       -32-  
  2133.           FUNCTION DateParse (s: STRING; VAR Dt: DateRec): BOOLEAN;
  2134.  
  2135.               Many programs  require the  user to  input a  date  using
  2136.           the console and this function is intended to make such  input
  2137.           easier.
  2138.  
  2139.               DateParse  attempts  to  convert   the  string   supplied
  2140.           as parameter s  to a date  in record Dt.   If the  conversion
  2141.           succeeds a result  of true  is  returned;  if the  conversion
  2142.           fails in any  way (including invalid dates such  as  February
  2143.           29,  1991) a value  of false is returned.
  2144.  
  2145.               DateParse is very flexible with  regard to the format  of
  2146.           the input  string.   The  string   should  consist  of  three
  2147.           distinct  parts: month, day, and year.   The month  may be  a
  2148.           number (1  through   12) or  an abbreviation  of the  month's
  2149.           name.  DateParse only   requires the  first three letters  of
  2150.           the month and ignores the rest of  the word.  Either upper or
  2151.           lower case may be used.  The  day and  year must be  numeric;
  2152.           the year may be specified  in full or abbreviated form  (e.g.
  2153.           1990 may be "1990" or just "90").    Note that the date  must
  2154.           be within the range January 1, 1900 through June 6, 2079  for
  2155.           DateParse to return true.
  2156.  
  2157.               Each part of the  date must have a  delimiter to separate
  2158.           it  from  the  other     parts,  and  when    using   numeric
  2159.           representation  of the  month  the  parts  must   be in   the
  2160.           correct sequence.    This  sequence must be month, day,  year
  2161.           if DateFormMDY is set or   day, month, year  if   DateFormDMY
  2162.           is  set.    When  using  the   default DateFormNumeric,   the
  2163.           sequence  is   determined  by   the   country setting in  the
  2164.           system's configuration file, as with DateStr.  The  following
  2165.           are all acceptable strings using the American  date format:
  2166.  
  2167.                           1/2/91          (January 2, 1991)
  2168.                           12.17.90        (December 17, 1990)
  2169.                           10-23-1990      (October 23, 1990)
  2170.                           7 4 91          (July 4, 1991)
  2171.                           09, 30,  90     (September 30, 1990)
  2172.                           11/20. 1990     (November 20, 1990)
  2173.  
  2174.           If the British date format   is selected with DateFormDMY  or
  2175.           from the  CONFIG.SYS file,  the  following strings  would  be
  2176.           accepted:
  2177.  
  2178.                           30 12 90        (December 30, 1990)
  2179.                           7/4/90          (April 7, 1990)
  2180.                           2, 1, 1991      (January 2, 1991)
  2181.                           17-12/1990      (December 17, 1990)
  2182.  
  2183.           Note that  several delimiters  are permissible  and may  even
  2184.           be mixed, as the last   example shows.   Spaces  or tabs  may
  2185.           follow  a delimiter and may themselves be used as delimiters.
  2186.           
  2187.           
  2188.                                       -33-  
  2189.               If the alphabetic  representation of the  month is  used,
  2190.           the string may  be in  the order  month, day,  year, or  day,
  2191.           month,  year.    The  following  are  all  acceptable  dates,
  2192.           whichever date format is currently selected:
  2193.  
  2194.                           January 2,91    (January 2, 1991)
  2195.                           DEC/17/90       (December 17, 1990)
  2196.                           23-Oct-1990     (October 23, 1990)
  2197.                           4 July, 91      (July 4, 1991)
  2198.                           sep.30.90       (September 30, 1990)
  2199.                           20 nov 90       (November 20, 1990)
  2200.  
  2201.  
  2202.               To clarify  the  way  in which  DateParse  operates,  the
  2203.           following examples show an  invalid string  which will  cause
  2204.           DateParse  to return a  result of false (American MDY  format
  2205.           is assumed):
  2206.  
  2207.                   9/31/90         (There is no September 31)
  2208.                   1jan 90         (No day/month delimiter)
  2209.                   fe 23 91        (Month abbreviation too short)
  2210.                   14,7,1990       (There is no fourteenth month)
  2211.                   6 /30/91        (Spaces cannot precede delimiter)
  2212.                   1990 Apr 3      (Year must be last item)
  2213.  
  2214.  
  2215.               The examples  show that  several delimiters  may be  used
  2216.           to separate the month,  day,  and year  fields.   The  global
  2217.           variable DateParseDelims  contains the  acceptable  delimiter
  2218.           characters  and is initialized to  the  string shown in   the
  2219.           introduction to  this unit.   The accepted delimiters may  be
  2220.           changed by assigning a   new string to DateParseDelims.   The
  2221.           assignment of '/- ' would  cause DateParse  to  accept   only
  2222.           the  three  characters  listed   as delimiters.  The  strings
  2223.           '1/2/90', '12-30-90',  and '17 DEC  90' would, therefore,  be
  2224.           acceptable, but '1.2.90'  and 'Dec 30,  90' would not.   Note
  2225.           that DateParse  will  always  accept  any  number  of  blanks
  2226.           (spaces  or tabs)  after a delimiter;  any number  of  blanks
  2227.           may also precede or follow the string as a whole.
  2228.  
  2229.               It is possible to have DateParse automatically supply the
  2230.           current year  if  none is  specified  by setting  the  global
  2231.           variable DateParseCurYear to true.   Strings supplied to  the
  2232.           function can  then consist  of just  the month  and day,  and
  2233.           DateParse will automatically obtain the year from the  system
  2234.           clock.  Input which specifies a  year will be treated in  the
  2235.           usual way.  DateParseCurYear is initialized to false.
  2236.  
  2237.               Setting the global variable  DateParseToDay to true  also
  2238.           modifies the  way in  which  DateParse interprets  the  input
  2239.           string.  With this setting, the function will accept a  null-
  2240.           string input (or a string which consists entirely of  blanks)
  2241.           and return true with the  current system date.  This  feature
  2242.           
  2243.           
  2244.                                       -34-  
  2245.           is useful in applications where the date being entered by the
  2246.           user is  frequently  the  current date.    DateParseToDay  is
  2247.           initialized to false.
  2248.  
  2249.               The final option available with DateParse uses the global
  2250.           variable DateParseCent21 and relates to  the use of dates  in
  2251.           the 21st century.  By default, any year entered as two digits
  2252.           is assumed  to be  in the  20th century,  so that  year  "xx"
  2253.           becomes "19xx."  Assigning a value to DateParseCent21  causes
  2254.           DateParse to  assume  that  two-digit  years  less  than  the
  2255.           specified value are to be treated as "20xx."   The  following
  2256.           examples   show   how   DateParse   interprets   input   when
  2257.           DateParseCent21 is set to 45:
  2258.  
  2259.                   1/1/99          (January 1, 1999)
  2260.                   7/10/62         (July 10, 1962)
  2261.                   1 1 00          (January 1, 2000)
  2262.                   7 Dec 41        (December 7, 2041)
  2263.                   7 Dec 1941      (December 7, 1941)
  2264.  
  2265.           The last example  shows that  a year entered  as four  digits
  2266.           will   always    be   interpreted    exactly   as    entered.
  2267.           DateParseCent21 is initialized to  zero; if no assignment  is
  2268.           made by your program then all dates from 2000 onward must  be
  2269.           entered as four digits.
  2270.  
  2271.           -------------------------------------------------------------
  2272.  
  2273.           FUNCTION TimeParse (s: STRING; VAR Tm: TimeRec): BOOLEAN;
  2274.  
  2275.               It is sometimes necessary  for  a  program to accept  the
  2276.           input of a  time from the  console or from  the command  line
  2277.           that  started  the program.   This function  will parse  such
  2278.           input and attempt   to  convert it  into a  variable of  type
  2279.           TimeRec.
  2280.  
  2281.               TimeParse converts a string supplied as parameter s to  a
  2282.           time value in the   three fields of  parameter  Tm.   If  the
  2283.           conversion succeeds a result  of  true is  returned;  if  the
  2284.           conversion  fails due to invalid  input, a value of false  is
  2285.           returned.
  2286.  
  2287.               TimeParse is flexible  with regard to  the format of  the
  2288.           input string.  Two distinct parts are required to specify the
  2289.           hours and minutes and a delimiter must separate  the  fields.
  2290.           Times may  be entered in  normal or military format;  in  the
  2291.           case of the   former an  "a" or "p"  after the minutes  field
  2292.           indicates a.m.  or  p.m.    The  following  are  examples  of
  2293.           acceptable input:
  2294.  
  2295.                           10:20           (10:20 a.m.)
  2296.                           5.50            (5:50 a.m.)
  2297.                           7 25a           (7:25 a.m.)
  2298.           
  2299.           
  2300.                                       -35-  
  2301.                           3.10 P          (3:10 p.m.)
  2302.                           11. 0 pm        (11:00 p.m.)
  2303.                           21:40           (9:40 p.m.)
  2304.                           0.15            (12:15 a.m.)
  2305.  
  2306.  
  2307.           TimeParse will reject any  input which has an  "a" or "p"  if
  2308.           the  hours  field  is  less  than  1  or  greater  than   12.
  2309.           Similarly, if the minutes field  is out of range,   TimeParse
  2310.           will return a value  of  false to the calling routine.   Note
  2311.           that there may  be any   number of blanks  (spaces or   tabs)
  2312.           after the   delimiter and that   blanks themselves  may be  a
  2313.           delimiter.
  2314.  
  2315.               The above  examples  show the  input  of just  hours  and
  2316.           minutes; the  seconds field  of Tm  is set  to zero  in  such
  2317.           cases.  It is also possible  to specify the seconds field  in
  2318.           the input string  by  the  addition of a   second  delimiter.
  2319.           Examples  of acceptable  input are:
  2320.  
  2321.                           3:50:30         (3:50:30 a.m.)
  2322.                           20.10.15        (8:10:15 p.m.)
  2323.                           7, 4, 55P       (7:04:55 p.m.)
  2324.                           9,0,58 a        (9:00:58 a.m.)
  2325.  
  2326.  
  2327.           The seconds field must come before any a.m. or p.m. indicator
  2328.           or it will not be recognized (TimeParse does not scan  beyond
  2329.           an  "a" or "p").
  2330.  
  2331.               To clarify  the  way  in which  TimeParse  operates,  the
  2332.           following examples show  an invalid string  which will  cause
  2333.           the function  to return a result of false:
  2334.  
  2335.                           3:62          (Minutes out of range)
  2336.                           0130          (No hours/minutes separator)
  2337.                           14.00p        (Mixed p.m. and military time)
  2338.                           2a            (No minutes field)
  2339.                           5 :35         (Space before delimiter)
  2340.  
  2341.  
  2342.               The  characters   acceptable   as   delimiters   may   be
  2343.           changed  by   assigning   a   new  string   to   the   global
  2344.           variable TimeParseDelims.  The initial string is shown in the
  2345.           introduction to  this section.     Assigning ':'  would   set
  2346.           TimeParse to  accept only the  two  characters specified   as
  2347.           delimiters.     The    strings '3:45p'  and  '15  21'  would,
  2348.           therefore, be acceptable, but  '3.45p' and '15,21' would not.
  2349.  
  2350.  
  2351.  
  2352.  
  2353.  
  2354.           
  2355.           
  2356.                                       -36-  
  2357.               Normally, TimeParse will not accept a null input and will
  2358.           return false.   Setting the global  variable TimeParseNow  to
  2359.           true causes TimeParse to accept a null-string (or a string of
  2360.           blanks) and return true with the current time from the system
  2361.           clock.   TimeParseNow is  initially set  to false  when  your
  2362.           program starts.
  2363.  
  2364.  
  2365.  
  2366.  
  2367.  
  2368.  
  2369.  
  2370.  
  2371.  
  2372.  
  2373.  
  2374.  
  2375.  
  2376.  
  2377.  
  2378.  
  2379.  
  2380.  
  2381.  
  2382.  
  2383.  
  2384.  
  2385.  
  2386.  
  2387.  
  2388.  
  2389.  
  2390.  
  2391.  
  2392.  
  2393.  
  2394.  
  2395.  
  2396.  
  2397.  
  2398.  
  2399.  
  2400.  
  2401.  
  2402.  
  2403.  
  2404.  
  2405.  
  2406.  
  2407.  
  2408.  
  2409.  
  2410.           
  2411.           
  2412.                                       -37-  
  2413.  
  2414.  
  2415.  
  2416.  
  2417.  
  2418.  
  2419.  
  2420.  
  2421.  
  2422.  
  2423.  
  2424.  
  2425.  
  2426.  
  2427.  
  2428.  
  2429.  
  2430.  
  2431.  
  2432.  
  2433.  
  2434.  
  2435.  
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.  
  2444.  
  2445.  
  2446.  
  2447.  
  2448.  
  2449.  
  2450.  
  2451.  
  2452.  
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.  
  2460.  
  2461.  
  2462.  
  2463.  
  2464.  
  2465.  
  2466.           
  2467.           
  2468.                                       -38-  
  2469.                                         5.
  2470.                                    UNIT STDERR 
  2471.           =============================================================
  2472.  
  2473.  
  2474.               Turbo Pascal's Write and WriteLn procedures normally send
  2475.           output to  the  operating system's  standard  output  device.
  2476.           This allows the pipe and  redirection commands to be used  on
  2477.           the command  line  to send  output  to a  file,  printer,  or
  2478.           another program.
  2479.  
  2480.               Many utilities can be written  to take advantage of  this
  2481.           redirection, which provides versatility  without the need  to
  2482.           complicate the program.  Most utility programs have the  need
  2483.           to produce an  error message  on occasions,  however, and  if
  2484.           this message  is sent  to the  standard output  device it  is
  2485.           possible that it will be  "lost."  Although the message  will
  2486.           appear in the redirected output (either on the printer, in  a
  2487.           file, or  as input  to another  program), it  is usually  far
  2488.           better to have the message sent to the console.
  2489.  
  2490.               When a Turbo Pascal program uses the CRT unit, a standard
  2491.           Write or  WriteLn procedure  no longer  sends output  to  the
  2492.           standard output device, but always  sends it the the  display
  2493.           console.  This would provide one solution to the problem, but
  2494.           requires that the program  specifically assigns and opens  an
  2495.           output channel for all  its regular output  which must go  to
  2496.           the standard  output device  (for full  details consult  your
  2497.           Turbo Pascal reference guide).
  2498.  
  2499.               This unit offers a simple solution which avoids the  need
  2500.           to use the  CRT unit in  such cases.   Only one procedure  is
  2501.           provided in the STDERR unit and it is used to send output  to
  2502.           the standard  error  device,  which  is  always  the  console
  2503.           display.
  2504.  
  2505.           -------------------------------------------------------------
  2506.  
  2507.           PROCEDURE WriteStdErr (s: STRING);
  2508.  
  2509.               WriteStdErr takes the  string passed as  parameter s  and
  2510.           sends it to the standard error device.  A carriage return and
  2511.           line feed  are  also sent  after  the string.    Because  the
  2512.           standard  error  device  is  always  the  screen,  any  error
  2513.           messages presented using this procedure cannot be  redirected
  2514.           and "lost" in a file.
  2515.  
  2516.               Note  that,  unlike  the   standard  Write  and   WriteLn
  2517.           procedures,  WriteStdErr  can  only  take  a  single   string
  2518.           argument, so any numeric output  must be converted to  string
  2519.           format first.
  2520.  
  2521.  
  2522.           
  2523.           
  2524.                                       -39-  
  2525.               While  the  function's   primary  purpose   is  that   of
  2526.           presentation of error  messages, WriteStdErr can  be used  to
  2527.           send any text  to the  screen.   For example,  a sign-on  and
  2528.           copyright notice  could be  displayed using  this  procedure,
  2529.           ensuring  that  when   the  program's   standard  output   is
  2530.           redirected the sign-on message is still sent to the console.
  2531.  
  2532.  
  2533.  
  2534.  
  2535.  
  2536.  
  2537.  
  2538.  
  2539.  
  2540.  
  2541.  
  2542.  
  2543.  
  2544.  
  2545.  
  2546.  
  2547.  
  2548.  
  2549.  
  2550.  
  2551.  
  2552.  
  2553.  
  2554.  
  2555.  
  2556.  
  2557.  
  2558.  
  2559.  
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.  
  2568.  
  2569.  
  2570.  
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.           
  2579.           
  2580.                                       -40-  
  2581.                                         6.
  2582.                                   UNIT CRTCLERR 
  2583.           =============================================================
  2584.  
  2585.               The standard  IBM  PC operating  system  incorporates  an
  2586.           error handler  which  is  called whenever  a  critical  error
  2587.           occurs. Critical  errors  are  caused by  such  things  as  a
  2588.           printer out  of  paper, a  communication  port not  ready  to
  2589.           accept data, or a disk drive with an open door.
  2590.  
  2591.               The critical-error handler presents  an error message  on
  2592.           the console, followed by "Abort, Retry, Ignore?"  or  "Abort,
  2593.           Retry, Fail?" depending on  the version of DOS  in use.   The
  2594.           user may then  decide whether to  retry the operation  (after
  2595.           correcting the cause of the error, by loading a printer  with
  2596.           paper or inserting a disk,  for example), abort the  program,
  2597.           or allow the  program to  continue by informing  it that  the
  2598.           operation failed.
  2599.  
  2600.               Turbo Pascal  installs  its  own  critical-error  handler
  2601.           which overrides  these  DOS  messages.   If  a  Turbo  Pascal
  2602.           program attempts to open a file on a drive which has no  disk
  2603.           in it, the operation fails and returns a suitable result code
  2604.           in  IOResult.    In  many  programs  this  action  is  ideal,
  2605.           especially when  the  screen  is  not  used  in  conventional
  2606.           teletype mode (i.e.  the appearance of the DOS error  message
  2607.           would disturb the screen layout).
  2608.  
  2609.               For some programs, however, it is more desirable that the
  2610.           usual critical-error message is presented when such an  error
  2611.           is encountered.  Most disk  utility programs would fall  into
  2612.           this category.  This unit enables the original critical-error
  2613.           handler to be restored by a Turbo Pascal program.
  2614.  
  2615.               The CRTCLERR  unit  defines one  new  type:  ErrorString.
  2616.           This is a string of up to 20 characters and is used to return
  2617.           an error message from the function CriticalErrorMsg.
  2618.  
  2619.               If all  that is  required is  for a  program to  use  the
  2620.           operating system's  critical-error handler  throughout,  then
  2621.           the only step necessary  is to declare  the CRTCLERR unit  in
  2622.           the program's USES statement.
  2623.  
  2624.           -------------------------------------------------------------
  2625.  
  2626.  
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.           
  2635.           
  2636.                                       -41-  
  2637.           PROCEDURE CriticalErrorDOS; 
  2638.           PROCEDURE CriticalErrorTP;
  2639.  
  2640.               These  two  procedures  allow  switching  between   Turbo
  2641.           Pascal's critical-error  handler  (CriticalErrorTP)  and  the
  2642.           operating system's handler (CriticalErrorDOS).
  2643.  
  2644.               Any critical error which  occurs after a  call to one  of
  2645.           these procedures will  be handled by  the specified  routine.
  2646.           Note that declaring  the CRTCLERR  unit in  a program's  USES
  2647.           statement automatically sets critical-error handling to  DOS,
  2648.           so it is only necessary to use these procedures if  different
  2649.           parts of the same  program must use different  critical-error
  2650.           handlers.
  2651.  
  2652.           -------------------------------------------------------------
  2653.  
  2654.           PROCEDURE CriticalErrorOwn (ErrAddr: POINTER);
  2655.  
  2656.               In some programs neither Turbo Pascal nor DOS can provide
  2657.           the correct  type of  critical-error  handling.   An  example
  2658.           would be  where  the  screen  is  divided  into  windows  and
  2659.           critical errors must  be presented to  the user by  way of  a
  2660.           window.
  2661.  
  2662.               In such cases, this procedure allows control to be passed
  2663.           to any routine when a critical error is detected.  The  value
  2664.           passed in parameter ErrAddr should be the address of your own
  2665.           critical-error handler routine.
  2666.  
  2667.               The exact details of how to write your own critical-error
  2668.           handler are outside the scope of this manual; this  procedure
  2669.           is provided for  those programmers who  are fully  conversant
  2670.           with such matters.   You  should carefully study  a good  DOS
  2671.           manual before attempting to use this routine.
  2672.  
  2673.           -------------------------------------------------------------
  2674.  
  2675.           FUNCTION CriticalErrorMsg (n: BYTE): ErrorString;
  2676.  
  2677.               This function is provided for  use in your own  critical-
  2678.           error handlers and may  be freely called  from within such  a
  2679.           handler.
  2680.  
  2681.               When DOS makes a call to the critical-error handler using
  2682.           interrupt 24  (hex.), the  DI register  holds a  value  which
  2683.           indicates the nature  of the error.   If the  value in DI  is
  2684.           passed to this function as  parameter n, a string  containing
  2685.           the appropriate error message is returned.  If the number  is
  2686.           not recognized, the message "Unknown error" is returned.
  2687.  
  2688.  
  2689.  
  2690.           
  2691.           
  2692.                                       -42-  
  2693.               The codes and messages supported are:
  2694.  
  2695.                           00      Write-protect error
  2696.                           01      Unknown unit
  2697.                           02      Drive not ready
  2698.                           03      Unknown command
  2699.                           04      Data error
  2700.                           05      Bad request
  2701.                           06      Seek error
  2702.                           07      Unknown disk format
  2703.                           08      Sector not found
  2704.                           09      Printer out of paper
  2705.                           0A      Write fault
  2706.                           0B      Read fault
  2707.                           0C      General error
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.           
  2747.           
  2748.                                       -43-  
  2749.  
  2750.  
  2751.  
  2752.  
  2753.  
  2754.  
  2755.  
  2756.  
  2757.  
  2758.  
  2759.  
  2760.  
  2761.  
  2762.  
  2763.  
  2764.  
  2765.  
  2766.  
  2767.  
  2768.  
  2769.  
  2770.  
  2771.  
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.  
  2778.  
  2779.  
  2780.  
  2781.  
  2782.  
  2783.  
  2784.  
  2785.  
  2786.  
  2787.  
  2788.  
  2789.  
  2790.  
  2791.  
  2792.  
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801.  
  2802.           
  2803.           
  2804.                                       -44-  
  2805.                                         7.
  2806.                                    UNIT ENHCON 
  2807.           =============================================================
  2808.  
  2809.               Many programs written for the  IBM PC need to  manipulate
  2810.           the display  in some  way  that is  not  catered for  by  the
  2811.           standard Pascal language.   Turbo Pascal's CRT unit  provides
  2812.           features designed specifically to take advantage of the  PC's
  2813.           console, such as cursor positioning and reading a single key-
  2814.           stroke.
  2815.  
  2816.               The ENHCON unit  expands upon the  facilities offered  by
  2817.           Borland's CRT  unit in  several  ways.   First, a  few  extra
  2818.           routines are provided for controlling some low-level  aspects
  2819.           of the display,  such as  adjusting the size  of the  cursor.
  2820.           Second, several functions are provided that allow strings and
  2821.           numbers to be edited on the  display; these will be found  to
  2822.           be useful again and again  in many interactive programs  that
  2823.           require input from the user.
  2824.  
  2825.               Third, a complete  set of routines  for handling  display
  2826.           windows is provided.  An application program can define up to
  2827.           255 different windows,  each of  which may set  its own  text
  2828.           attribute and cursor, and may define a border with header and
  2829.           footer text.  The area  of  screen which  is occupied  by  an
  2830.           opened window  may  be  saved,  thus  enabling  the  original
  2831.           contents to be  restored when the  window is closed.   It  is
  2832.           also possible to remove a window from the screen but preserve
  2833.           its contents.  These routines allow the simple development of
  2834.           programs which require status  lines, "pop-up" menus, and  so
  2835.           on.
  2836.  
  2837.               Finally, the unit provides a simple way to implement  on-
  2838.           line help systems  for application programs.   The help  text
  2839.           may consist of up to 255 sections, each of which may have  up
  2840.           to 1,000 lines  of text.   Each  section name  appears in  an
  2841.           index, allowing the user to select the required topic.
  2842.  
  2843.               This  unit  requires  Borland's  CRT  unit  in  order  to
  2844.           operate,  but  it  is  not  necessary  for  your  program  to
  2845.           specifically include  CRT in  its USES  statement, unless  it
  2846.           also accesses routines  in the  CRT unit directly.   If  your
  2847.           program does use CRT, it  is most important that you  declare
  2848.           ENHCON after  CRT in  your USES  statement (i.e.  "USES  CRT,
  2849.           ENHCON;" is acceptable but "USES ENHCON, CRT;" is not).   The
  2850.           reason for this  is that  ENHCON "hooks" into  some of  CRT's
  2851.           routines in order to modify their operation.
  2852.  
  2853.               You should  be aware  of the  fact that  the ENHCON  unit
  2854.           accesses memory  directly and  makes  extensive use  of  BIOS
  2855.           routines.  This means  that any program  using this unit  may
  2856.           not work on systems that  do not have full PC  compatibility.
  2857.           This is also true of any program that uses Turbo Pascal's own
  2858.           
  2859.           
  2860.                                       -45-  
  2861.           CRT unit.   As  the  programmer, you  must make  a  trade-off
  2862.           between compatibility  and the  features  you would  like  to
  2863.           implement.
  2864.  
  2865.           -------------------------------------------------------------
  2866.  
  2867.           DISPLAY ATTRIBUTE CONSTANTS
  2868.  
  2869.               Turbo Pascal's  CRT unit  defines several  text-attribute
  2870.           constants  for  color  displays,  but  overlooks  those   for
  2871.           monochrome systems.    The  following  constants  may  be  be
  2872.           assigned to the  CRT unit's  TextAttr variable  when using  a
  2873.           monochrome display.
  2874.  
  2875.                       MonoNormal          Normal text
  2876.                       MonoUnderline       Underlined text
  2877.                       MonoIntense         Intensified text
  2878.                       MonoIntenseUL       Intensified and underlined
  2879.                       MonoReverse         Reverse video (dark on light)
  2880.                       MonoNone            Blank, or hidden, text
  2881.  
  2882.  
  2883.  
  2884.           EXTENDED KEY HANDLING AND READKEY FUNCTION
  2885.  
  2886.               The standard IBM PC keyboard provides a comprehensive set
  2887.           of extended keys  - keys which  do not have  a regular  ASCII
  2888.           code, such as Home, End, PgUp, PgDn, etc.  Programs can  make
  2889.           use of  these function  keys in  many ways,  but use  of  the
  2890.           standard ReadKey  function  in the  CRT  unit can  make  this
  2891.           application somewhat complex, because of the way in which  it
  2892.           returns information about these extended keys.
  2893.  
  2894.               Normally, keys which have a standard ASCII code, such  as
  2895.           letters, numbers, carriage-return, and  so on, cause  ReadKey
  2896.           to return the appropriate ASCII code.  Extended keys cause  a
  2897.           zero, or null,  to be returned  and it is  then necessary  to
  2898.           call ReadKey a second time to get the scan code for the key.
  2899.  
  2900.               To simplify keyboard input, ENHCON was designed to modify
  2901.           the behavior  of ReadKey  so that  it only  returns a  single
  2902.           value for either  normal ASCII characters  or extended  keys.
  2903.           All 256  possible values  of  a character-type  variable  are
  2904.           assigned in  the  IBM  PC,  the values  80  through  FF  hex.
  2905.           representing  mathematical  symbols,  graphics,  and  foreign
  2906.           alphabets.   Some programs  may  need to  send one  of  these
  2907.           characters to the  display, but  it is  highly unlikely  that
  2908.           they would need to input such a character from the  keyboard;
  2909.           standard keyboards can only generate these codes by the  Alt-
  2910.           keypad method anyway.
  2911.  
  2912.  
  2913.  
  2914.           
  2915.           
  2916.                                       -46-  
  2917.               ENHCON modifies ReadKey to use  the values 80 through  FF
  2918.           hex. to represent extended key-strokes.  The assigned  values
  2919.           are defined as constants in the interface section of  ENHCON,
  2920.           and the identifiers may be used  in your program.  Note  that
  2921.           an S, A,  or C after  "Key" represents Shift,  Alt, or  Ctrl,
  2922.           respectively (e.g.  "KeyCHome" is  the key-stroke  Ctrl-Home,
  2923.           and "KeyAX" is the key-stroke Alt-X).
  2924.  
  2925.  
  2926.           Constant  Value        Constant   Value       Constant  Value
  2927.           KeyIns      80         KeyF1       A0         KeyAA        E1
  2928.           KeyDel      81         KeyF2       A1         KeyAB        E2
  2929.           KeyUp       82         KeyF3       A2         KeyAC        E3
  2930.           KeyDown     83         KeyF4       A3         KeyAD        E4
  2931.           KeyLeft     84         KeyF5       A4         KeyAE        E5
  2932.           KeyRight    85         KeyF6       A5         KeyAF        E6
  2933.           KeyHome     86         KeyF7       A6         KeyAG        E7
  2934.           KeyEnd      87         KeyF8       A7         KeyAH        E8
  2935.           KeyPgUp     88         KeyF9       A8         KeyAI        E9
  2936.           KeyPgDn     89         KeyF10      A9         KeyAJ        EA
  2937.                                                         KeyAK        EB
  2938.           KeyCLeft    8A         KeySF1      B0         KeyAL        EC
  2939.           KeyCRight   8B         KeySF2      B1         KeyAM        ED
  2940.           KeyCHome    8C         KeySF3      B2         KeyAN        EE
  2941.           KeyCEnd     8D         KeySF4      B3         KeyAO        EF
  2942.           KeyCPgUp    8E         KeySF5      B4
  2943.           KeyCPgDn    8F         KeySF6      B5         KeyAP        F0
  2944.                                  KeySF7      B6         KeyAQ        F1
  2945.           KeyA0       90         KeySF8      B7         KeyAR        F2
  2946.           KeyA1       91         KeySF9      B8         KeyAS        F3
  2947.           KeyA2       92         KeySF10     B9         KeyAT        F4
  2948.           KeyA3       93                                KeyAU        F5
  2949.           KeyA4       94         KeyCF1      C0         KeyAV        F6
  2950.           KeyA5       95         KeyCF2      C1         KeyAW        F7
  2951.           KeyA6       96         KeyCF3      C2         KeyAX        F8
  2952.           KeyA7       97         KeyCF4      C3         KeyAY        F9
  2953.           KeyA8       98         KeyCF5      C4         KeyAZ        FA
  2954.           KeyA9       99         KeyCF6      C5
  2955.                                  KeyCF7      C6
  2956.           KeyAHyphen  9A         KeyCF8      C7
  2957.           KeyAEquals  9B         KeyCF9      C8
  2958.                                  KeyCF10     C9
  2959.           PoundSign   9C
  2960.                                  KeyAF1      D0
  2961.           KeySTab     9D         KeyAF2      D1
  2962.                                  KeyAF3      D2
  2963.           KeyCPrtSc   9E         KeyAF4      D3
  2964.                                  KeyAF5      D4
  2965.                                  KeyAF6      D5
  2966.                                  KeyAF7      D6
  2967.                                  KeyAF8      D7
  2968.                                  KeyAF9      D8
  2969.                                  KeyAF10     D9
  2970.           
  2971.           
  2972.                                       -47-  
  2973.               A call to ReadKey, therefore, causes a single value to be
  2974.           returned - either a standard ASCII code or one of the  values
  2975.           listed above.  For example, the Backspace key returns a value
  2976.           of 08 hex.  (the ASCII  code for Ctrl-H) and the F1  function
  2977.           key returns  A0  hex.   The  Alt-keypad method  for  entering
  2978.           characters will only  work for standard  ASCII characters  in
  2979.           the range  01 through  7E,  and for  the  code 9C  hex.  (156
  2980.           decimal).
  2981.  
  2982.               Note that a constant, PoundSign, has been defined as  the
  2983.           value 9C  hex.   British keyboards  have the  pounds-sterling
  2984.           sign where American  keyboards have the  "#" symbol, so  this
  2985.           code is left unchanged  to enable this  symbol to be  entered
  2986.           correctly on such systems.
  2987.  
  2988.               The  IBM  PC  keyboard  offers  four  toggles:  capitals,
  2989.           number, scroll, and insert lock, each changed by pressing the
  2990.           appropriate lock  key.   The first  three simply  change  the
  2991.           status of the appropriate lock,  but do not return any  value
  2992.           to ReadKey.  For  some curious reason,  pressing the Ins,  or
  2993.           Insert, key not only toggles the lock status but also returns
  2994.           an extended key code.
  2995.  
  2996.               A good many programs  make use of the  Ins key to  switch
  2997.           between insert and overwrite  modes, and use the  appropriate
  2998.           lock-status flag to determine the  current mode.  This  means
  2999.           that the program must disregard calls to ReadKey which return
  3000.           the Ins  key's code.    The enhanced  version of  ReadKey  in
  3001.           ENHCON causes  depressions of  the Ins  or Insert  key to  be
  3002.           ignored, relieving the programmer of  this extra work.   This
  3003.           facility can  be overridden  if desired,  causing ReadKey  to
  3004.           return a code  of 80 hex.  when Ins is  pressed.  The  global
  3005.           boolean variable InsKeyEnable should be set true to cause the
  3006.           Ins key to be treated as a regular extended key, or false  to
  3007.           cause ReadKey to ignore it.  InsKeyEnable is set to false  by
  3008.           default.
  3009.  
  3010.           -------------------------------------------------------------
  3011.  
  3012.           FUNCTION ColorDisplay: BOOLEAN;
  3013.  
  3014.               This function returns true if the program is running on a
  3015.           system which has  a color display  or false if  running on  a
  3016.           monochrome system.  If the computer has both a monochrome and
  3017.           a color display, the value returned indicates the type of the
  3018.           currently active display.
  3019.  
  3020.           -------------------------------------------------------------
  3021.  
  3022.  
  3023.  
  3024.  
  3025.  
  3026.           
  3027.           
  3028.                                       -48-  
  3029.           PROCEDURE GetMaxXY (VAR x, y: BYTE);
  3030.  
  3031.               GetMaxXY sets the variables specified as parameters x and
  3032.           y to the  number of  columns and rows,  respectively, of  the
  3033.           current display  mode.   A standard  monochrome display  will
  3034.           return x as 80 and y as 25.
  3035.  
  3036.               This routine will be found  useful for console input  and
  3037.           output routines which must work  with a variety of  different
  3038.           display adapters and modes.
  3039.  
  3040.           -------------------------------------------------------------
  3041.  
  3042.           FUNCTION GetDisplayPage: BYTE;
  3043.  
  3044.               All of  IBM's  display  adapters, except  the  basic  MDA
  3045.           (monochrome), support multiple display  pages.  Turbo  Pascal
  3046.           does not provide  full support  for this  facility, but  some
  3047.           applications may benefit from using two or more pages.
  3048.  
  3049.               The current  version of  ENHCON  does not  provide  page-
  3050.           switching support, but  this function is  used by some  other
  3051.           routines and  was included  in the  unit's interface  on  the
  3052.           grounds  that  it  could   be  useful  for  developing   such
  3053.           applications.
  3054.  
  3055.               GetDisplayPage  returns  the  number  of  the   currently
  3056.           selected page, which will usually be zero.
  3057.  
  3058.           -------------------------------------------------------------
  3059.  
  3060.           FUNCTION GetDisplayBase: WORD;
  3061.  
  3062.               Some programs need to access  the display in a way  which
  3063.           can only  be  achieved  by directly  storing  values  in  the
  3064.           display memory.    This  function  aids  calculation  of  the
  3065.           display address by returning the base segment address for the
  3066.           currently selected display adapter and page.
  3067.  
  3068.               GetDisplayBase  will  usually  return  B000  hex.  for  a
  3069.           monochrome display and B800 hex.  for a color display, unless
  3070.           a page other than zero is selected.  A description of the way
  3071.           in which display memory is used  is beyond the scope of  this
  3072.           manual; consult your system's documentation for details.
  3073.  
  3074.           -------------------------------------------------------------
  3075.  
  3076.           FUNCTION MaxCursorSize: BYTE;
  3077.  
  3078.               The display adapters  employed by  the IBM  PC allow  the
  3079.           size of the cursor  to be adjusted by  software.  The  cursor
  3080.           size is set by specifying the starting and ending scan lines.
  3081.           The top line of a character position is line zero; the number
  3082.           
  3083.           
  3084.                                       -49-  
  3085.           of lines per position is  dependent upon the type of  display
  3086.           adapter in use.  The CGA color display has 8 scan lines;  the
  3087.           EGA color and MDA monochrome adapters both have 14 lines.
  3088.  
  3089.               This function checks the display type in use and  returns
  3090.           a value that  represents the highest-numbered  scan line  for
  3091.           the current mode.  A CGA system causes the returned value  to
  3092.           be 07 hex.  and a  monochrome or  EGA color  system sets  the
  3093.           returned value to 0D hex.
  3094.  
  3095.               Note that the new  VGA color adapters  have a mode  which
  3096.           emulates the cursor of the CGA; the ENHCON unit automatically
  3097.           sets a VGA display to this mode upon initialization.
  3098.  
  3099.           -------------------------------------------------------------
  3100.  
  3101.           PROCEDURE SetCursor (size: WORD);
  3102.  
  3103.               This procedure adjusts the cursor size to that  specified
  3104.           by the parameter.  Size is a two-byte value - the upper  byte
  3105.           represents the  starting scan  line and  the lower  byte  the
  3106.           ending scan line (the standard monochrome cursor of two  scan
  3107.           lines, for example, is represented by the value 0B0C hex.).
  3108.  
  3109.               If your program switches to  a different display mode  at
  3110.           any point in its operation, then the cursor size is reset  to
  3111.           the default for the new display mode.
  3112.  
  3113.               Note that if  the cursor  is hidden,  SetCursor does  not
  3114.           automatically make it visible  again - it  just sets the  new
  3115.           size to be used  when the cursor  is re-enabled.   Similarly,
  3116.           SetCursor cannot be used to  set to disable-cursor bit -  the
  3117.           procedure HideCursor  should be  used  instead.   You  should
  3118.           consult your system's documentation for details before  using
  3119.           this procedure if you  are unfamiliar with  the way in  which
  3120.           the cursor can be manipulated.
  3121.  
  3122.           -------------------------------------------------------------
  3123.  
  3124.           FUNCTION GetCursor: WORD;
  3125.  
  3126.               GetCursor provides the converse function to SetCursor and
  3127.           returns the size of the  current cursor.  Like SetCursor,  it
  3128.           ignores the state of the cursor-hide bit and will return  the
  3129.           cursor size as though the  cursor were actually enabled  (you
  3130.           should use the CursorHidden function to test the  cursor-hide
  3131.           bit).
  3132.  
  3133.           -------------------------------------------------------------
  3134.  
  3135.  
  3136.  
  3137.  
  3138.           
  3139.           
  3140.                                       -50-  
  3141.           PROCEDURE HideCursor (hide: BOOLEAN);
  3142.  
  3143.               The SetCursor and  GetCursor routines allow  the size  of
  3144.           the cursor to be handled;  HideCursor allows it to be  hidden
  3145.           and restored.
  3146.  
  3147.               Calling this  procedure  with  parameter  hide  set  true
  3148.           causes the cursor to be  disabled by setting the hide-bit  in
  3149.           the cursor control word.  Calling with hide set false  causes
  3150.           the cursor to be restored.  A typical use would be to  remove
  3151.           the cursor from the screen  while presenting the user with  a
  3152.           menu display.
  3153.  
  3154.               Note that calling HideCursor does not affect the size  of
  3155.           the cursor; the cursor will be  restored to the same size  it
  3156.           was before  it was  hidden, unless  SetCursor was  called  in
  3157.           between.
  3158.  
  3159.               If  your  program  switches  display  modes  by   calling
  3160.           TextMode, then the cursor  is automatically made visible  and
  3161.           reset to the default size for the new mode.
  3162.  
  3163.           -------------------------------------------------------------
  3164.  
  3165.           FUNCTION CursorHidden: BOOLEAN;
  3166.  
  3167.               This function checks the cursor-control word and  returns
  3168.           true if the  cursor is  currently hidden  or false  if it  is
  3169.           visible.
  3170.  
  3171.               Manuals for the IBM BIOS sometimes list ways in which the
  3172.           cursor may  be hidden,  other than  by setting  the  disable-
  3173.           cursor flag in the control word.  All the cursor routines  in
  3174.           this unit expect that the cursor will be hidden only by using
  3175.           the appropriate  flag and  CursorHidden  looks only  at  this
  3176.           flag.  So long  as you only control  the cursor by using  the
  3177.           facilities provided by ENHCON, there will be no conflict.
  3178.  
  3179.           -------------------------------------------------------------
  3180.  
  3181.           PROCEDURE LineCursor; 
  3182.           PROCEDURE BlockCursor;
  3183.  
  3184.               The  cursor-control  routines  above  allow  for  maximum
  3185.           flexibility  when  manipulating  the  cursor,  but  SetCursor
  3186.           requires careful handling of the cursor's size specification.
  3187.           Many programs require nothing more than the ability to select
  3188.           a line cursor, a block cursor, or no cursor.
  3189.  
  3190.               These two  procedures allow  simple switching  between  a
  3191.           line or  block cursor.    A program  may call  LineCursor  or
  3192.           BlockCursor without  any  consideration  as to  the  type  of
  3193.           display in use; ENHCON  automatically determines the  correct
  3194.           
  3195.           
  3196.                                       -51-  
  3197.           values to pass to SetCursor for the requested size.
  3198.  
  3199.               As with SetCursor, calling either of these routines  does
  3200.           not automatically  enable the  cursor if  it is  hidden;  the
  3201.           procedures simply adjust the size so that the new cursor will
  3202.           appear after a call to HideCursor to re-enable it.
  3203.  
  3204.           -------------------------------------------------------------
  3205.  
  3206.           INSERT/OVERWRITE CURSOR SWITCHING
  3207.  
  3208.               It has become common practice  to change the size of  the
  3209.           cursor when the  insert mode  status is changed.   The  usual
  3210.           arrangement is to have a line cursor for overwrite mode and a
  3211.           block cursor for insert mode.
  3212.  
  3213.               ENHCON  allows  this  cursor   switching  to  be   easily
  3214.           accomplished; all  that is  necessary is  to set  the  global
  3215.           boolean variable  CursorInsert  to true.    The size  of  the
  3216.           cursor is updated whenever a call  to ReadKey is made and  it
  3217.           does not matter whether InsKeyEnable is set to true or  false
  3218.           (see Extended key handling, above).  You should note that the
  3219.           cursor switching will not take place if you call the standard
  3220.           input procedures Read or ReadLn. One of the main aims of  the
  3221.           ENHCON unit was to simplify console input and output for  the
  3222.           type of display-oriented programs  that are so common  today,
  3223.           so it is unlikely that the standard input procedures would be
  3224.           used.
  3225.  
  3226.               Should you  wish  to  disable the  cursor  switching  for
  3227.           certain parts of  your program,  you may  accomplish this  by
  3228.           setting CursorInsert back to false.   The cursor may be  left
  3229.           as a line or a block, depending upon the state of the  insert
  3230.           toggle at the time, so if you want the cursor to be set to  a
  3231.           specific  size   you  should   call  SetCursor,   LineCursor,
  3232.           BlockCursor, or OrigCursor immediately after.
  3233.  
  3234.           -------------------------------------------------------------
  3235.  
  3236.           PROCEDURE OrigCursor;
  3237.  
  3238.               The unit  automatically saves  the cursor  size and  hide
  3239.           status when your program is  run and restores them when  your
  3240.           program terminates.  This ensures that cursor changes in your
  3241.           program are not carried back to the DOS prompt.
  3242.  
  3243.               OrigCursor may  be called  to accomplish  the same  thing
  3244.           part way through your program.  If you have switched  display
  3245.           modes by  calling TextMode,  OrigCursor recalls  the  default
  3246.           cursor that was set up for the new mode.
  3247.  
  3248.           -------------------------------------------------------------
  3249.  
  3250.           
  3251.           
  3252.                                       -52-  
  3253.           FUNCTION CapsLock: BOOLEAN; 
  3254.           FUNCTION NumLock: BOOLEAN; 
  3255.           FUNCTION ScrollLock: BOOLEAN; 
  3256.           FUNCTION InsertLock: BOOLEAN;
  3257.  
  3258.               These four  functions allow  your  program to  check  the
  3259.           current state of each of the four keyboard toggles: capitals,
  3260.           number, scroll, and insert lock.  Each function returns  true
  3261.           if the appropriate toggle is set or false if it is clear.
  3262.  
  3263.               InsertLock is used to check whether typed text should  be
  3264.           inserted in a  string or overwrite  the current contents  and
  3265.           will be  found useful  in  developing editing  routines  (the
  3266.           source code  for the  EditString routine  in this  unit is  a
  3267.           typical example). Scroll  lock is  used by  some programs  to
  3268.           change the  action of  cursor  movement keys,  a  spreadsheet
  3269.           being a case in point. CapsLock and NumLock will probably  be
  3270.           used  only   very  occasionally,   but  were   included   for
  3271.           completeness.
  3272.  
  3273.           -------------------------------------------------------------
  3274.  
  3275.           PROCEDURE ForceInsert (Ins: BOOLEAN);
  3276.  
  3277.               ForceInsert may be  used to  set the insert  toggle to  a
  3278.           known state, at the  start of a  program or editing  routine,
  3279.           for example. If parameter  Ins is true the  toggle is set  on
  3280.           (insert mode);  if Ins  is  false it  is set  off  (overwrite
  3281.           mode).
  3282.  
  3283.               If the  automatic  insert/overwrite cursor  switching  is
  3284.           enabled, the  cursor will  be  updated at  the next  call  to
  3285.           ReadKey.
  3286.  
  3287.               The  inclusion  of  procedures  to  force  the  capitals,
  3288.           number,  and  scroll  lock  toggles  to  a  known  state  was
  3289.           considered during the development of this unit.  The decision
  3290.           was made  not  to  provide  them,  however,  because  of  the
  3291.           difficulty of keeping  keyboard indicators synchronized  with
  3292.           the toggle.   Many  keyboards provide  three lock  indicators
  3293.           which show the  current state  of the  capitals, number,  and
  3294.           scroll toggles.  Forcing  specific values into these  toggles
  3295.           usually does not update the indicators, which results in  the
  3296.           light being on when the lock is off, and vice versa.
  3297.  
  3298.           -------------------------------------------------------------
  3299.  
  3300.           PROCEDURE FlushKB;
  3301.  
  3302.               The IBM PC  buffers keyboard input  to allow  type-ahead,
  3303.           although the size of the buffer is extremely limited.   There
  3304.           are many times in a program when it is not desirable to allow
  3305.           such buffering; a typical example is a check-point which asks
  3306.           
  3307.           
  3308.                                       -53-  
  3309.           "Are you sure?"
  3310.  
  3311.               Calling FlushKB  causes  the  contents  of  the  keyboard
  3312.           buffer to be flushed, thereby preventing previous key-strokes
  3313.           from being read by the next  call for input.  FlushKB  should
  3314.           be called immediately before the input routine that must  not
  3315.           allow buffered input to be used.
  3316.  
  3317.           -------------------------------------------------------------
  3318.  
  3319.           EDITING ROUTINES
  3320.  
  3321.               The  ENHCON  unit  provides  five  functions  that  allow
  3322.           different types of  data to  be displayed and  edited on  the
  3323.           screen:  EditString,   EditInt,   EditReal,   EditDate,   and
  3324.           EditTime.
  3325.  
  3326.               Each routine allows the programmer to position the cursor
  3327.           at the start of  an editing field  on the display,  highlight
  3328.           the field, and then accept user input.  A parameter, form, is
  3329.           passed to  the  appropriate  routine and  this  controls  the
  3330.           format of  the edit.   Each  field of  this record  (of  type
  3331.           EditFormatRec)  is  described  in  detail  in  the  following
  3332.           sections.
  3333.  
  3334.               EditFormatRec  =  RECORD
  3335.                                   Attribute:      BYTE;
  3336.                                   StartChar,
  3337.                                   EndChar:        CHAR;
  3338.                                   MarkerAttr:     BYTE;
  3339.                                   AllowChars,
  3340.                                   ExitKeys:       CharSet;
  3341.                                   EditKey,
  3342.                                   RestoreKey,
  3343.                                   AbortKey:       CHAR;
  3344.                                   NumFormat:      STRING[12];
  3345.                                   SignalError:    SignalErrorProc;
  3346.                                   Flags:          WORD;
  3347.                                 END;
  3348.  
  3349.           -------------------------------------------------------------
  3350.  
  3351.           FUNCTION EditString (form:      EditFormatRec;
  3352.                                VAR s:     STRING;
  3353.                                width:     BYTE): CHAR;
  3354.  
  3355.               This function may be called  to edit any string,  subject
  3356.           to the string having a maximum length of 80 characters  (i.e.
  3357.           the largest field  that will  fit across  a standard  display
  3358.           screen).
  3359.  
  3360.               Before calling EditString the cursor should be positioned
  3361.           at the first character of the desired position of the editing
  3362.           
  3363.           
  3364.                                       -54-  
  3365.           field on the  display.   The string  to be  edited should  be
  3366.           supplied as  parameter s  and its  maximum length  should  be
  3367.           passed as parameter width.  This value determines the  number
  3368.           of characters  that  will be  used  on the  display  for  the
  3369.           editing field.   It  is  the programmer's  responsibility  to
  3370.           ensure  that  the  cursor   position  and  field  width   are
  3371.           consistent, so that the  field does not run  off the edge  of
  3372.           the display.
  3373.  
  3374.  
  3375.           MARKING THE FIELD
  3376.  
  3377.               There are  two ways  in which  the editing  field may  be
  3378.           highlighted on the screen.  If the Attribute field of form is
  3379.           set to a non-zero  value, then that value  is used as a  text
  3380.           attribute.  If,  for  example,   form.Attribute  is  set   to
  3381.           MonoReverse, then the editing  field is displayed in  reverse
  3382.           video.   Note that  the  whole field  is highlighted  to  the
  3383.           specified field width, even if  the string, s, is shorter  in
  3384.           length.  If  Attribute is  set to zero,  EditString does  not
  3385.           change the text attribute and the field will be displayed  in
  3386.           whatever value was  in TextAttr  at the  time EditString  was
  3387.           called.
  3388.  
  3389.               The alternative  way to  mark the  editing field  on  the
  3390.           screen is  to have  a marker  character at  each end  of  the
  3391.           field.  Setting StartChar in  form to a character other  than
  3392.           NUL (i.e. #0) causes the specified character to be  displayed
  3393.           immediately to the left of the first character of the editing
  3394.           field.  In a similar way,  EndChar controls the display of  a
  3395.           character immediately after the  last position of the  field.
  3396.           A typical program would use arrow characters to point to  the
  3397.           field being edited (e.g.  character  codes #16 and #17).   If
  3398.           you use a start- or  end-of-field marker character, you  must
  3399.           ensure that space exists on the screen for these  characters.
  3400.           (You should not  try to  use StartChar if  the editing  field
  3401.           starts in the first  display column, for instance.)  Whenever
  3402.           form specifies that a start- or end-of-field marker is to  be
  3403.           used, EditString uses the value supplied in field  MarkerAttr
  3404.           as the  text attribute  for the  markers.   If MarkerAttr  is
  3405.           zero, the characters  are displayed with  whatever value  was
  3406.           set in TextAttr when EditString was called.
  3407.  
  3408.               Most programs will use only  one of the above methods  to
  3409.           mark the field being edited, but EditString allows both to be
  3410.           used simultaneously if  desired.  If  no highlighting of  the
  3411.           field is required, just set StartChar and EndChar to NUL  and
  3412.           Attribute to zero.  This  disables the marker characters  and
  3413.           causes  the  field  to  be  displayed  in  the  current  text
  3414.           attribute, as described above.
  3415.  
  3416.  
  3417.  
  3418.           
  3419.           
  3420.                                       -55-  
  3421.           BASIC EDITING
  3422.  
  3423.               EditString automatically uses six keys to permit editing:
  3424.           Home, End, cursor left, cursor right, Backspace, and  Delete.
  3425.           The use  of  these  keys  is fairly  obvious,  but  they  are
  3426.           summarized here for sake of completeness.
  3427.  
  3428.                   Home            Move to start of string
  3429.                   End             Move to end of string
  3430.                   Cursor Left     Move left one character
  3431.                   Cursor Right    Move right one character
  3432.                   Backspace       Delete character to left of cursor
  3433.                   Delete          Delete character at cursor
  3434.  
  3435.  
  3436.           The exact action  of some  of these keys  may vary  depending
  3437.           upon the  configuration set  up in  form.   Such details  are
  3438.           listed where appropriate in the following sections.
  3439.  
  3440.               Five of  the  fields  in the  parameter  form  allow  the
  3441.           various editing  keys  to  be  defined.    These  fields  are
  3442.           AllowChars,  ExitKeys,  RestoreKey,  AbortKey,  and  EditKey.
  3443.           AllowChars is of type  CharSet, a set  of characters, and  is
  3444.           used to set which  characters may be  entered in the  string.
  3445.           For example,  if  the  string being  edited  should  only  be
  3446.           allowed  to  hold  capital  letters  and  numbers,  the   set
  3447.           ['A'..'Z', '0'..'9'] should  be assigned to  form.AllowChars;
  3448.           any other keys pressed during  the edit will then be  ignored
  3449.           by EditString.  The interface section of ENHCON defines a set
  3450.           called StandardChars, which will be found useful for  general
  3451.           string editing.  Assigning this set to AllowChars allows  any
  3452.           of the  standard printable  characters  to be  entered  (i.e.
  3453.           ASCII characters 32 through 126 decimal).
  3454.  
  3455.               ExitKeys is also defined as  type CharSet and is used  to
  3456.           hold the  keys  which  will  terminate  the  edit  and  cause
  3457.           EditString to  return  to  its  calling  program.    In  many
  3458.           programs, assigning the simple  set [CR] will be  sufficient,
  3459.           allowing the carriage-return,  or Enter, key  to signal  that
  3460.           editing has been completed.   Other applications may  require
  3461.           that several keys are available  to exit from EditString.   A
  3462.           data entry screen which uses the cursor keys to move from one
  3463.           field to another, for example,  would require ExitKeys to  be
  3464.           set to  a larger  set (e.g.  [CR, KeyLeft,  KeyRight,  KeyUp,
  3465.           KeyDown, KeyF10]).   Note that EditString  uses the  enhanced
  3466.           version of  ReadKey, so  all  keys are  defined as  a  single
  3467.           character value.
  3468.  
  3469.               Whenever a key  that is  listed in  ExitKeys is  pressed,
  3470.           EditString updates  the edited  string (parameter  s) to  the
  3471.           current contents of the edit field and returns to the calling
  3472.           program. The  character-type  result  of  EditString  is  the
  3473.           character code of the key  that was pressed to terminate  the
  3474.           
  3475.           
  3476.                                       -56-  
  3477.           edit.  Using the example shown in the last paragraph, a  code
  3478.           of 0D hex. would  be returned if the  edit was terminated  by
  3479.           the Enter key,  but A9  hex. would  be returned  if the  user
  3480.           finished the edit  by pressing F10.  This feature allows  the
  3481.           calling routine to determine which key terminated the edit so
  3482.           that it may take the  appropriate action (moving to the  next
  3483.           or previous field, for instance).
  3484.  
  3485.               Note that it is quite permissible to define a key in both
  3486.           AllowChars and ExitKeys.  If  this is done, pressing the  key
  3487.           will first enter the character into the string being  edited,
  3488.           then cause EditString to terminate as usual.
  3489.  
  3490.               Before returning, EditString removes any highlighting  of
  3491.           the editing  field.    The  field  itself  is  re-written  in
  3492.           whatever text attribute was  set when EditString was  called.
  3493.           If start- or end-of-field  marker characters were used,  they
  3494.           are  replaced  by  whatever  character  was  on  the   screen
  3495.           previously.   Finally,  the  cursor  is  left  at  the  first
  3496.           position of the editing  field (i.e. the  same place as  when
  3497.           the edit function was called).
  3498.  
  3499.  
  3500.           RESTORE AND ABORT
  3501.  
  3502.               EditString makes a copy  of the string  s upon entry  and
  3503.           allows it to be restored at  any time during the edit by  the
  3504.           user pressing a  single key.   The key  to be  used for  this
  3505.           purpose should be assigned to  the RestoreKey field of  form.
  3506.           If, for example, RestoreKey is set to KeyF2 (value A1  hex.),
  3507.           then pressing  F2 will  throw away  any changes  made to  the
  3508.           string since EditString was called; the cursor is returned to
  3509.           the first character in  the field so the  user may start  the
  3510.           edit again.  The restore feature may be disabled by assigning
  3511.           NUL to form.RestoreKey.
  3512.  
  3513.               In a  similar way,  a key  may be  assigned to  AbortKey.
  3514.           Pressing the abort  key during  an edit  causes the  original
  3515.           string to  be restored  and the  edit routine  to  terminate.
  3516.           EditString returns the  character code for  the abort key  so
  3517.           that the  calling  routine  may  detect  the  abort  and  act
  3518.           accordingly.  If the abort  facility is not required, it  may
  3519.           be disabled by assigning NUL to form.AbortKey.
  3520.  
  3521.               It is acceptable for RestoreKey and AbortKey to hold  the
  3522.           same value  so  that  the  same key  may  be  used  for  both
  3523.           purposes.  The restore action  is performed whenever the  key
  3524.           is pressed, but  EditString only  terminates if  the key  was
  3525.           pressed when the string  had not been  edited.  For  example,
  3526.           assume that RestoreKey and AbortKey are both set to ESC.   If
  3527.           EditString is called and the  Escape key is pressed  straight
  3528.           away,  the  string  has  not  been  edited  so  the   routine
  3529.           terminates and returns the ESC code.  If the string is edited
  3530.           
  3531.           
  3532.                                       -57-  
  3533.           and then Escape is pressed,  the original string is  restored
  3534.           and the edit is allowed continue.  (Pressing Escape a  second
  3535.           time, with no  other intervening keys,  would then  terminate
  3536.           the edit.)
  3537.  
  3538.  
  3539.           FLAGS
  3540.  
  3541.               The Flags field  of form  contains 16 flags,  not all  of
  3542.           which are  used  in  the  current version  of  ENHCON.    The
  3543.           interface section of the source code lists several  constants
  3544.           which may be  used to  build the  flags value  for a  format.
  3545.           These values are summarized here  and each flag is  described
  3546.           in detail below.
  3547.  
  3548.               EdFlagFlushKB       Flush keyboard buffer before edit
  3549.               EdFlagInsert        Select insert mode
  3550.               EdFlagForceIns      Force insert toggle to selected state
  3551.               EdFlagInsStat       Allow insert/overwrite switching
  3552.               EdFlagFirstClr      First character clears field
  3553.               EdFlagEdKeyExit     Allow standard edit key to terminate
  3554.               EdFlagHideCursor    Hide cursor before edit
  3555.  
  3556.               EdFlagTrimL         Remove leading blanks
  3557.               EdFlagTrimR         Remove trailing blanks
  3558.               EdFlagPadL          Pad with leading blanks
  3559.               EdFlagPadR          Pad with trailing blanks
  3560.               EdFlagUpper         Force upper case
  3561.  
  3562.           The constants  for   the required   flags  should   be  added
  3563.           together when setting the Flags field of form.  Example:
  3564.  
  3565.             Flags := EdFlagFirstClr + EdFlagHideCursor + EdFlagInsStat;
  3566.  
  3567.           sets the  three  flags  specified, leaving  all  other  flags
  3568.           clear.
  3569.  
  3570.  
  3571.           INSERT AND OVERWRITE MODES
  3572.  
  3573.               The  three   flags  EdFlagInsert,   EdFlagForceIns,   and
  3574.           EdFlagInsStat are used to control the way in which EditString
  3575.           uses insert  and overwrite  modes.   If all  three flags  are
  3576.           clear, overwrite  mode  is  selected.   In  this  mode  typed
  3577.           characters  overwrite  existing  characters  in  the  string;
  3578.           pressing Backspace moves the cursor to the left and  replaces
  3579.           the character there with a space - it does not "close up" the
  3580.           string.
  3581.  
  3582.               If EdFlagInsert is set, insert  mode is selected.   Typed
  3583.           characters are  inserted at  the cursor,  pushing  everything
  3584.           beyond the  cursor  one  position  to  the  right  (the  last
  3585.           character of the field is lost).  Pressing Backspace while in
  3586.           
  3587.           
  3588.                                       -58-  
  3589.           insert mode deletes the character  to the left of the  cursor
  3590.           and moves everything beyond the cursor back one position.
  3591.  
  3592.               The two settings  described above fix  EditString to  one
  3593.           mode or the  other; they do  not allow the  Insert key to  be
  3594.           used to switch  modes.  If  EdFlagInsStat is set,  EditString
  3595.           checks the current Insert lock  status each time a  character
  3596.           is typed.  This  allows the Insert key  to be used to  toggle
  3597.           between insert and overwrite modes.
  3598.  
  3599.               Setting EdFlagForceIns  causes  the  insert  lock  to  be
  3600.           forced to a known state at  the start of the edit, the  state
  3601.           used being that set in EdFlagInsert (i.e. EdFlagForceIns  and
  3602.           EdFlagInsert forces  insert  mode, but  EdFlagForceIns  alone
  3603.           forces overwrite mode). EdFlagInsStat  must still be set  for
  3604.           the  Insert  key   to  be   used  to   toggle  insert   mode;
  3605.           EdFlagForceIns simply ensures  that the  toggle is  set to  a
  3606.           specific value at each call to EditString.
  3607.  
  3608.  
  3609.           Summary:
  3610.                   No flags
  3611.                       Fix in overwrite mode
  3612.  
  3613.                   EdFlagInsert
  3614.                       Fix in insert mode
  3615.  
  3616.                   EdFlagInsStat
  3617.                       Allow Ins key to toggle mode
  3618.  
  3619.                   EdFlagInsStat + EdFlagForceIns
  3620.                       Allow Ins key toggle, but start in overwite mode
  3621.  
  3622.                   EdFlagInsStat + EdFlagForceIns + EdFlagInsert
  3623.                       Allow Ins key toggle, but start in insert mode
  3624.  
  3625.  
  3626.           FIELD CLEARING AND EDIT KEYS
  3627.  
  3628.               The flag EdFlagFirstClr  determines the  action taken  by
  3629.           EditString when the first key  is pressed to start the  edit.
  3630.           By default, the first key pressed  is added to the string  in
  3631.           the usual way, either by  overwriting the first character  or
  3632.           by being inserted before the first character.
  3633.  
  3634.               If EdFlagFirstClr  is  set,  the  first  character  typed
  3635.           causes the field  to be  cleared.  Any  cursor movement  made
  3636.           before the  first allowable  character is  typed causes  this
  3637.           blanking to be disabled.  This arrangement lets the user edit
  3638.           the existing  string  by moving  the  cursor and  making  the
  3639.           changes, but  also gives  a "clean  slate" when  entering  an
  3640.           entirely new string.
  3641.  
  3642.           
  3643.           
  3644.                                       -59-  
  3645.               In the section Basic editing  an example was given  which
  3646.           showed the  cursor left  and right  keys used  as exit  keys.
  3647.           This would appear to  create a conflict:  Both keys are  exit
  3648.           keys and both keys perform cursor movement within the editing
  3649.           field. EditString usually  handles such conflicts  in a  very
  3650.           simple way.  If  the  key  is the  first  key  pressed  after
  3651.           EditString was  called  (or the  first  key pressed  after  a
  3652.           restore action has been performed),  then the key is  treated
  3653.           as an exit key and terminates  the edit accordingly.  If  the
  3654.           key is pressed after an edit has started, it is treated as  a
  3655.           cursor-movement key.
  3656.  
  3657.               Setting the  flag  EdFlagEdKeyExit causes  edit/exit  key
  3658.           conflicts to  be  handled in  quite  a different  way  -  the
  3659.           editing function of any edit key which is defined as an  exit
  3660.           key is simply disabled.   The cursor left  and right keys  in
  3661.           the  above  example,  therefore,  would  terminate  the  edit
  3662.           whenever they were pressed; it  would not be possible to  use
  3663.           the cursor keys to move around  the field itself.  It is  not
  3664.           advisable to define the Backspace key as an exit key if  this
  3665.           flag is set;  doing so would  leave the user  no easy way  to
  3666.           correct typing errors.
  3667.  
  3668.               The final  item  regarding field  clearing  concerns  the
  3669.           EditKey field in the form record.  When EdFlagFirstClr is set
  3670.           it is possible to edit the existing contents of the field  by
  3671.           moving the cursor with  the left or right  arrow keys, or  by
  3672.           pressing Home  or End.   This  removes the  "not yet  edited"
  3673.           signal and prevents the first allowable character typed  from
  3674.           clearing the field.   If  the cursor movement  keys have  all
  3675.           been defined  as  exit keys  this  is not  possible,  because
  3676.           pressing  any  one  of  them  to  start  editing  will  cause
  3677.           EditString to  terminate.    Pressing  a  regular  character,
  3678.           however, will cause the existing  contents of the edit  field
  3679.           to be deleted.
  3680.  
  3681.               You may define a key that will allow the user to edit the
  3682.           existing string in such circumstances by assigning a value to
  3683.           form.EditKey.  Pressing  the edit key  tells EditString  that
  3684.           the first  allowable character  typed  should not  cause  the
  3685.           field to be cleared.  You may use EditKey even if the regular
  3686.           cursor movement keys are  not defined as  exit keys, and  you
  3687.           can avoid defining an edit key by assigning a code of NUL.
  3688.  
  3689.  
  3690.           CURSOR CONTROL
  3691.  
  3692.               By default,  EditString  does not  change  the  display's
  3693.           cursor in  any way;  whatever size  cursor is  selected  when
  3694.           EditString is called is used throughout the edit.
  3695.  
  3696.               If you  have enabled  insert/overwrite switching  of  the
  3697.           cursor by setting CursorInsert to true, then the Ins key will
  3698.           
  3699.           
  3700.                                       -60-  
  3701.           still change the  size of  the cursor  accordingly.   Whether
  3702.           EditString recognizes this switching  depends upon the  state
  3703.           of the appropriate flags in the format record.  If your  edit
  3704.           format has fixed insert or overwrite mode and you do not want
  3705.           the Ins key  to change  the cursor  for the  duration of  the
  3706.           edit, you should disable the cursor switching before  calling
  3707.           EditString.
  3708.  
  3709.               The flag EdFlagHideCrsr  in form.Flags allows  EditString
  3710.           to manipulate the cursor to  a limited degree.  Setting  this
  3711.           flag causes the edit  routine to hide  the cursor when  first
  3712.           called.  As soon  as editing starts, by  the user moving  the
  3713.           cursor or  entering text,  the cursor  is re-enabled.    This
  3714.           arrangement may be used to  keep the cursor hidden while  the
  3715.           user moves up or down to the required field on the screen; it
  3716.           is turned on  only when  needed to edit  the selected  field.
  3717.           When EditString terminates, the cursor's hide status is reset
  3718.           to that upon entry.
  3719.  
  3720.  
  3721.           STRING FORMATTING
  3722.  
  3723.               Normally, EditString returns with the variable  specified
  3724.           as parameter s set to the  exact string that the user  typed,
  3725.           with any leading or trailing spaces included.  The string may
  3726.           vary in length from zero to the value specified in  parameter
  3727.           width.
  3728.  
  3729.               The flags EdFlagTrimL and  EdFlagTrimR allow leading  and
  3730.           trailing spaces, respectively, to be removed from the  edited
  3731.           string.  You may set either  or both of these flags and  when
  3732.           EditString terminates it will re-write the adjusted string in
  3733.           the editing  field.   These  flags  are useful  for  trimming
  3734.           strings entered  by the  user where  extra spaces  may  cause
  3735.           alignment problems, for example.
  3736.  
  3737.               EdFlagPadL and EdFlagPadR  perform the converse  function
  3738.           and ensure that the edited string is of the length  specified
  3739.           in parameter width by adding  spaces to the beginning  (PadL)
  3740.           or end (PadR)  of the  string.  You  may set  both flags  but
  3741.           EdFlagPadL takes precedence, so spaces  will be added to  the
  3742.           start of the string only.
  3743.  
  3744.               The trim and pad options  may be combined to justify  the
  3745.           edited string.   Combining  EdFlagTrimL and  EdFlagPadR,  for
  3746.           example, ensures that the  final string is left-justified  by
  3747.           trimming leading spaces  and then adding  trailing spaces  to
  3748.           the required  field width.   A  detailed description  of  the
  3749.           trim, pad, and justify functions will be found in the STRINGS
  3750.           unit's documentation.
  3751.  
  3752.               Finally, the flag  EdFlagUpper may  be set  to force  all
  3753.           alphabetic characters  to  upper case.    EditString  usually
  3754.           
  3755.           
  3756.                                       -61-  
  3757.           treats upper- and  lower-case letters as  different; if  only
  3758.           one type is  defined in form.AllowChars  then the other  type
  3759.           will be rejected. Setting  EdFlagUpper causes all  lower-case
  3760.           letters to be  converted to capitals  before being  processed
  3761.           any further.
  3762.  
  3763.  
  3764.           MISCELLANEOUS CONFIGURATION CONTROL
  3765.  
  3766.               The final flag defined by  the current version of  ENHCON
  3767.           is EdFlagFlushKB.   Setting  this  flag causes  the  keyboard
  3768.           buffer to  be  flushed  at  each  call  to  EditString,  thus
  3769.           preventing key-strokes  left in  the buffer  from before  the
  3770.           call from being accepted.
  3771.  
  3772.               The fields NumFormat and SignalError in form are not used
  3773.           by EditString.  Their use is described in the  number-editing
  3774.           routines.
  3775.  
  3776.           -------------------------------------------------------------
  3777.  
  3778.           FUNCTION EditReal (form:      EditFormatRec;
  3779.                              VAR r:     REAL;
  3780.                              min, max:  REAL): CHAR;
  3781.  
  3782.               This function provides a way to conveniently display  and
  3783.           edit real  numbers  on  the  console's  display.    The  real
  3784.           variable to be edited should  be supplied as parameter r  and
  3785.           the cursor  should be  moved  to the  first position  of  the
  3786.           required field  on the  screen. The  parameters min  and  max
  3787.           should be set to numbers representing the minimum and maximum
  3788.           allowable value for r.
  3789.  
  3790.               EditReal takes a  format record as  a parameter, just  as
  3791.           EditString does, and each field  of this record controls  one
  3792.           aspect of the  way in  which EditReal operates.   The  fields
  3793.           Attribute, StartChar, EndChar, MarkerAttr, ExitKeys, EditKey,
  3794.           RestoreKey, and AbortKey  work in exactly  the same way  (see
  3795.           EditString  for  details).     The   characters  defined   in
  3796.           AllowChars are ignored; EditReal  will accept the  characters
  3797.           necessary to form a  valid number.  Almost  all of the  flags
  3798.           also perform the  same functions  as in  EditString, but  the
  3799.           PadL, PadR, TrimL, and TrimR flags are ignored.
  3800.  
  3801.               EditReal does, however, use the NumFormat field of  form.
  3802.           NumFormat should be set to  a string suitable for passing  to
  3803.           the Format function in the STRINGS unit.  This string is used
  3804.           to determine the way in which  the real number is   displayed
  3805.           and follows the rules laid down by  the Format function.  You
  3806.           should be thoroughly  familiar with the  way in which  Format
  3807.           works  before attempting to use EditReal.
  3808.  
  3809.  
  3810.           
  3811.           
  3812.                                       -62-  
  3813.               The total width  of the  editing field is  determined  by
  3814.           the width specified  in  NumFormat  (i.e.  the  length  of  a
  3815.           string returned by STRINGS.Format).    Format  is called   to
  3816.           convert  the supplied  number into  a  displayable  form  and
  3817.           then  the user  may enter  a new number or edit the  existing
  3818.           one.   For  example,  if the  string  in  form.NumFormat  was
  3819.           '+10:3'   and  the initial  value  of   r  was  470.58,  then
  3820.           EditReal  would start by   displaying a field  10  characters
  3821.            wide containing  "   +470.580".   Note that  you should  not
  3822.           attempt to use  vulgar-fraction notation in  a format  string
  3823.           passed to EditReal, as the  function will not recognize  this
  3824.           format.
  3825.  
  3826.               Once the user has entered  a new value, EditReal  adjusts
  3827.           it to the format specified in NumFormat  and terminates.  The
  3828.           existing value may be  accepted, of course,  by just pressing
  3829.           one of    the exit  keys,  just  as with  EditString.    (The
  3830.           numerical edit routines actually  convert the   number to   a
  3831.           string using  Format and  then call EditString to perform the
  3832.           editing.)
  3833.  
  3834.               Because of  the way   in which   EditReal is  written,  a
  3835.           handy programming  trick using  the plus  and minus  keys  is
  3836.           possible.   It is  sometimes useful to  be  able to enter   a
  3837.           number and  terminate  its entry by  pressing plus or  minus.
  3838.           If the plus  and minus   keys are  defined in  form.ExitKeys,
  3839.           EditReal  allows  this -  the  number  will be  positive   or
  3840.           negative   as  appropriate    and EditReal    will  return  a
  3841.           character of "+" or "-".
  3842.  
  3843.  
  3844.           EXPONENTIAL NOTATION
  3845.  
  3846.               There is one case in which the number initially displayed
  3847.           by EditReal  does   not  conform   to  the   way  in    which
  3848.           STRINGS.Format  handles  real  numbers.    If  the   decimals
  3849.           specifier in NumFormat  is zero (e.g. '12:0' or '12'), then r
  3850.           is shown in exponential   form. The above example of  470.580
  3851.           would be displayed as "  4.70580E+02" if the field width  was
  3852.           12 characters.   When exponential format  is used, any  other
  3853.           options listed in  NumFormat are  also ignored;   it is  most
  3854.           unlikely that  zero-fill, floating  dollar signs,  and so  on
  3855.           would be required with such formats anyway.
  3856.  
  3857.               It is not a good idea to   try to use the plus and  minus
  3858.           keys as exit keys  when working  in exponential  format; real
  3859.           numbers displayed in this form may  need  two signs, one  for
  3860.           the  mantissa and one for the exponent.
  3861.  
  3862.  
  3863.  
  3864.  
  3865.  
  3866.           
  3867.           
  3868.                                       -63-  
  3869.           RANGE AND CONVERSION ERRORS
  3870.  
  3871.               If EditReal  cannot   successfully  convert   the  number
  3872.           entered from  a   string  to   a real    value   or if    the
  3873.           converted    value    is  outside  the  range  specified   by
  3874.           parameters min and max, a call  to form.SignalError is  made.
  3875.           SignalError is  a  field   which  is defined as a  procedural
  3876.           variable -  a call  to  SignalError   results  in a  call  to
  3877.           whatever procedure name was stored in SignalError.
  3878.  
  3879.               You   can    use     ENHCON's   default    routine     by
  3880.           assigning StdSignalError in your format record, e.g.
  3881.  
  3882.                   MyFormat.SignalError := StdSignalError;
  3883.  
  3884.           Under  these   conditions  a   conversion  or   range   error
  3885.           causes  EditReal  to  generate  a  beep  and  re-display  the
  3886.           original number so that the user may try again.
  3887.  
  3888.               In some  programs it  may be  desirable for  the computer
  3889.           to display a short error message on  a status line or open  a
  3890.           window on the  screen   to provide  assistance.     This  can
  3891.           be   done    by  assigning  your   own    error-handler    to
  3892.           SignalError.    There   are several conditions which must  be
  3893.           strictly adhered to  if your   own  error routine  is not  to
  3894.           upset the  operation of  EditReal.    First,  your  procedure
  3895.           must  take a  single  value  of type  byte  as  a  paramater.
  3896.           Your procedure  heading should  look something  like this:
  3897.  
  3898.                   PROCEDURE MyRealErrorSignal (width: BYTE);
  3899.  
  3900.  
  3901.               Second, the procedure must  be compiled in  the far model
  3902.           by placing it after a  $F+ directive or by  having it  appear
  3903.           in   the  interface  section of    a  unit.     This    is  a
  3904.           requirement of  Turbo Pascal's procedural variables.
  3905.  
  3906.               Third, your procedure must return with certain aspects of
  3907.           the display exactly the same as when your routine was called.
  3908.           Any of the following items which are  changed by your routine
  3909.           should    be  restored   to  their  original  values   before
  3910.           returning: the  position  of the cursor;  the size and  hide-
  3911.           status of the cursor; the  value of TextAttr.
  3912.  
  3913.               When  your  routine   is  called  the   cursor  will   be
  3914.           left positioned  at  the  start  of  the  editing  field  and
  3915.           paramater  width will hold the   width of the  field.    This
  3916.           enables you  to put  a short  message in  the editing   field
  3917.           should you    so  desire   (note  that  when    your  routine
  3918.           returns, however,  the edit   field  will revert back to  its
  3919.           original contents).
  3920.  
  3921.  
  3922.           
  3923.           
  3924.                                       -64-  
  3925.               Note that a   format  record which   is  to be   used  by
  3926.           EditReal must  have  some  valid procedure  assigned  to  its
  3927.           SignalError field.  If  a range    or conversion    error  is
  3928.           detected and  this field  is uninitialized, a  call will   be
  3929.           made   to some    random address    in memory,  causing  your
  3930.           program to fail.
  3931.  
  3932.           -------------------------------------------------------------
  3933.  
  3934.           FUNCTION EditInt (form:        EditFormatRec;
  3935.                             VAR i:       LongInt;
  3936.                             min, max:    LongInt): CHAR;
  3937.  
  3938.               EditInt works in  a very   similar way  to EditReal,  but
  3939.           allows integers to   be  edited.    All   of the   facilities
  3940.           available  in EditString and  EditReal are also available  in
  3941.           EditInt,  including the use of form.SignalError to install an
  3942.           error-handling  routine for conversion and range errors.
  3943.  
  3944.               The  NumFormat   field   of  form   is   handled   in   a
  3945.           slightly different  way   by  EditInt,  however.     If   the
  3946.           format  string  specifies no  decimal places, as   you  would
  3947.           expect  for  an    integer  value,  then  it  is  passed   to
  3948.           STRINGS.Format in the usual way.   Any of the valid   options
  3949.           of Format  may  be used.    For example,   the format  string
  3950.           '6+' would  cause the value 45  to be displayed  as "   45+".
  3951.           Note that the total   field width is  that specified  in  the
  3952.           format string, just as with EditReal.
  3953.  
  3954.               EditInt also  provides for   an  assumed decimal   point,
  3955.           thus allowing an integer variable to hold fixed-decimal-point
  3956.           values. The format string  in NumFormat specifies  the number
  3957.           of  assumed decimal places   (e.g.  '12:3'  specifies   three
  3958.           assumed  decimal places)  and  EditInt   displays the   value
  3959.           with a   decimal   point inserted at  the appropriate  place.
  3960.           For example, a value  of 1,258 is displayed   as "12.58"   if
  3961.           two   decimal  places   are   specified.  Similarly,  numbers
  3962.           entered  by   the   user   are   converted   in   a  converse
  3963.           manner, so that  "3.47"   would be  returned as  an   integer
  3964.           value of  347  (again  assuming   that  two  decimal   places
  3965.           were specified).
  3966.  
  3967.               A typical example of using assumed decimal places is that
  3968.           of an  accounts program.   It  is common  practice to  use  a
  3969.           LongInt-type variable  to  store  amounts  of  money  -  this
  3970.           enables  faster    integer  arithmetic  to  be  employed  and
  3971.           eliminates rounding  errors that  may appear  if real  values
  3972.           were used.  An  amount of  $12.75 would  be stored as  1,275,
  3973.           for example  (i.e. the value   gives the  amount directly  in
  3974.           cents).   To display a monetary  value and allow  the user to
  3975.           edit it,   EditInt may be  called  with  two decimal   places
  3976.           specified.  The  value  is  thus presented   in the  familiar
  3977.           manner and the user may enter a new value in the same format.
  3978.           
  3979.           
  3980.                                       -65-  
  3981.               The following  examples should  help clarify  the use  of
  3982.           assumed decimal places:
  3983.  
  3984.                   Value         Format string         Displayed as
  3985.  
  3986.                   1,234         10:2                        12.34
  3987.                     475         10:1                         47.5
  3988.                   2,700         10:4                       0.2700
  3989.  
  3990.  
  3991.                 User's entry    Format string           Returned value
  3992.  
  3993.                   37.05           10:2                        3,705
  3994.                   50              10:5                    5,000,000
  3995.                   4.6             10:3                        4,600
  3996.  
  3997.  
  3998.  
  3999.               Any of the  display options that  STRINGS.Format  accepts
  4000.           may also  be   used    when   specifying   assumed    decimal
  4001.           places.    For instance, the  format  "$8:2+" would cause   a
  4002.           value of  500 to  be displayed as "  $5.00+".
  4003.  
  4004.           -------------------------------------------------------------
  4005.  
  4006.           FUNCTION EditDate (form:EditFormatRec; VAR Dt:DateRec): CHAR; 
  4007.           FUNCTION EditTime (form:EditFormatRec; VAR Tm:TimeRec): CHAR;
  4008.  
  4009.               These two functions are closely associated with the  TIME
  4010.           unit and  allow console  editing of a   date or  time.    You
  4011.           should  be  thoroughly  familiar  with  the TIME unit  before
  4012.           attempting to use either of these routines.
  4013.  
  4014.               The values passed in parameter  form control the edit  in
  4015.           the same  way   as  they   do    for EditString,    with  the
  4016.           exception   that characters  specified   in AllowChars    are
  4017.           ignored  (both   routines automatically accept the  necessary
  4018.           characters  to form a date  or time).   The cursor  should be
  4019.           positioned at   the start   of   the  required editing  field
  4020.           before calling EditDate  or EditTime  and the date or time to
  4021.           be   edited  should  be  suplied as  parameter    Dt  or  Tm,
  4022.           respectively.
  4023.  
  4024.               EditDate converts  parameter Dt  into a  displayable date
  4025.           by calling the DateStr function in the TIME unit.  The  exact
  4026.           format of  the   string    is,  therefore,   determined    by
  4027.           the   current configuration of  the unit.  DateStr returns  a
  4028.           string with  a maximum length of nine characters, so EditDate
  4029.           automatically uses an editing   field of   this width.    The
  4030.           new, or   edited,  string  entered by the  user is  converted
  4031.           back to a date record by  calling the TIME  unit's  DateParse
  4032.           function.    Again, the   way in   which DateParse  processes
  4033.           the string  is  dependent upon  the  current settings in  the
  4034.           
  4035.           
  4036.                                       -66-  
  4037.           TIME unit itself.
  4038.  
  4039.               In a   similar   way, EditTime   converts   parameter  Tm
  4040.           into  a displayable string by  calling the TimeStr   function
  4041.           in the  TIME unit and processes  the user's  input by calling
  4042.           TimeParse.   As with EditDate,  the   exact  format used   is
  4043.           dependent  upon  the current settings in the  TIME unit,  but
  4044.           EditTime always uses  an editing field  13  characters   wide
  4045.           (the  maximum  length  of  a variable of type TimeString).
  4046.  
  4047.               The SignalError field of parameter form is used the  same
  4048.           way as in  the  edit  number  routines.   You  should  assign
  4049.           either StdSignalError or  your   own  error-handler to   this
  4050.           field;   the  specified procedure  is  called whenever    the
  4051.           entered date or  time cannot be successfully converted.   All
  4052.           rules regarding the use of this facility are the same as  for
  4053.           the number  routines (see   Range  and conversion  errors  in
  4054.           EditReal).   The  NumFormat field  of   form  is  ignored  by
  4055.           EditDate and EditTime.
  4056.  
  4057.           -------------------------------------------------------------
  4058.  
  4059.           USING DISPLAY WINDOWS
  4060.  
  4061.               Up to 255 user-defined windows are available; window zero
  4062.           is pre-defined and refers to the whole screen.
  4063.  
  4064.               The data type  WindowDefinition is used  to hold all  the
  4065.           basic  information   required     to   define     a   window.
  4066.           WindowDefinition  is  dependent  upon     two    other   data
  4067.           types:   WindowBorder   and WindowJustify.
  4068.  
  4069.             WindowBorder      =  ARRAY[1..8] OF CHAR;
  4070.             WindowJustify     =  (WJustLeft, WJustCenter, WJustRight);
  4071.  
  4072.             WindowDefinition  =  RECORD
  4073.                                    X1, Y1, X2, Y2:  BYTE;
  4074.                                    DefaultAttr:     BYTE;
  4075.                                    DefaultCrsrHide: BOOLEAN;
  4076.                                    DefaultCrsrSize: BYTE;
  4077.                                    Border:          WindowBorder;
  4078.                                    BorderAttr:      BYTE;
  4079.                                    HdrText,
  4080.                                    FtrText:         ConsoleStr;
  4081.                                    HdrAttr,
  4082.                                    FtrAttr:         BYTE;
  4083.                                    HdrPos,
  4084.                                    FtrPos:          WindowJustify;
  4085.                                    Flags:           BYTE:
  4086.                                  END;
  4087.  
  4088.  
  4089.  
  4090.           
  4091.           
  4092.                                       -67-  
  4093.               Fields X1  and  Y1 specify  the  top-left corner  of  the
  4094.           required window (as  column and  row respectively),  numbered
  4095.           as   for    the  GotoXY procedure.    The  standard  80-by-25
  4096.           display, therefore,   has rows numbered  1  through  25   and
  4097.           columns numbered  1 through  80. Fields X2 and Y2 specify the
  4098.           bottom-right corner of the  required window.
  4099.  
  4100.               DefaultAttr determines the  text attribute that  will  be
  4101.           set when the window   is opened.   Assigning  a value  of  01
  4102.           hex.,  for example, will  cause text written into the  window
  4103.           to be underlined on a monochrome  display or blue on a  color
  4104.           display.
  4105.  
  4106.               The two fields DefaultCrsrHide   and DefaultCrsrSize  are
  4107.           used to   control  the   cursor.     The   first   determines
  4108.           whether  the particular  window  has  a  visible  cursor   or
  4109.           not.     Setting  DefaultCrsrHide to true causes the   cursor
  4110.           to be hidden when  the window is opened; setting  it to false
  4111.           ensures  that  a cursor   is visible, even  if it was  hidden
  4112.           before the window was opened.
  4113.  
  4114.               DefaultCrsrSize is  used   to control  the   size of  the
  4115.           cursor, and may be  set to any  valid values for  the display
  4116.           adapter   in use.   The  value  used will  be passed  to  the
  4117.           SetCursor routine  when the  window  is opened;  whether  the
  4118.           cursor will  actually be  visible or  not depends  upon   the
  4119.           setting of   DefaultCrsrHide.   There  are  three key  values
  4120.           which may also  be assigned to  DefaultCrsrSize and these are
  4121.           defined as constants:
  4122.  
  4123.                           WCrsrDefault    =  $FF00;
  4124.                           WCrsrLine       =  $FE00;
  4125.                           WCrsrBlock      =  $FD00;
  4126.  
  4127.  
  4128.           WCrsrLine and  WCrsrBlock are    provided to  allow   you  to
  4129.           define  a line or block cursor for  the window without having
  4130.           to  calculate the  actual values (which   will vary from  one
  4131.           type of display   to another).     Assigning  one   of  these
  4132.           values   to   DefaultCrsrSize causes  the appropriate  cursor
  4133.           size to  be  set when the  window  is  opened.  The  constant
  4134.           WCrsrDefault may be  used if  the size of  the cursor  should
  4135.           remain unchanged;  opening  the  window will  still  set  the
  4136.           cursor  to  hidden  or  visible, but  its  size  will  remain
  4137.           unaltered.
  4138.  
  4139.  
  4140.  
  4141.  
  4142.  
  4143.  
  4144.  
  4145.  
  4146.           
  4147.           
  4148.                                       -68-  
  4149.               Two fields  control the  way  in which  a border   around
  4150.           the window may be  shown on  the display.   The  field Border
  4151.           allows eight characters to be defined:
  4152.  
  4153.                           Index           Position
  4154.                             1             Top left corner
  4155.                             2             Top line
  4156.                             3             Top right corner
  4157.                             4             Right side
  4158.                             5             Bottom right corner
  4159.                             6             Bottom line
  4160.                             7             Bottom left corner
  4161.                             8             Left side
  4162.  
  4163.  
  4164.           Typed-constants are  defined  to enable  four  commonly  used
  4165.           borders to be assigned to Border easily.  These are:
  4166.  
  4167.               Border1         A single-line border
  4168.               Border2         A double-line border
  4169.               BorderV1H2      Single vertical, double horizontal lines
  4170.               BorderH1V2      Single horizontal, double vertical lines
  4171.  
  4172.  
  4173.               BorderAttr defines  the text  attribute to  be used   for
  4174.           the display of each  border character and  determines how the
  4175.           border will appear on the screen.  If a window is defined  as
  4176.           not  having a border (see description  of flags, below)  then
  4177.           the Border  and BorderAttr fields are ignored.
  4178.  
  4179.               Header text can  also be placed  in the top  border of  a
  4180.           window. This text may   be used to   provide a   title for  a
  4181.           menu or  other window.  The string to be  displayed should be
  4182.           stored in  HdrText  and the required  text attribute for  the
  4183.           title should be   assigned to  HdrAttr.    The HdrPos   field
  4184.           controls the  positioning of  the text  and  may  be  set  to
  4185.           one   of    three   values:      WJustLeft,  WJustCenter,  or
  4186.           WJustRight.   These cause the   title to be   left-justified,
  4187.           centered,  or right-justified,  respectively.   If  no header
  4188.           is required, HdrText  should  be set to   a null string   and
  4189.           the HdrAttr   and HdrPos   fields are   then ignored.     The
  4190.           maximum length of the header text  is less than the width  of
  4191.           the  window's border, because the two corners are  not  used;
  4192.           if HdrText is  too long it is truncated.
  4193.  
  4194.               In a similar   way, the   fields FtrText,   FtrAttr,  and
  4195.           FtrPos allow  text  to overwrite  the  bottom   border  of  a
  4196.           window.  As  with the header definition, setting FtrPos  to a
  4197.           null string  prevents any footer from being displayed.
  4198.  
  4199.               Note that the header and footer options are used only  if
  4200.           the window is defined  as having a   border.  If  the  window
  4201.           does   not have  a   border, all   six   header  and   footer
  4202.           
  4203.           
  4204.                                       -69-  
  4205.           control  fields  are ignored.
  4206.  
  4207.               The final field of WindowDefinition contains a collection
  4208.           of flags.  Six are   used in the  current  version of  ENHCON
  4209.           and   they are  defined as  constants.     A more    detailed
  4210.           description of  each  flag is provided   in later   sections,
  4211.           but  the following  summary provides a quick overview.
  4212.  
  4213.               WFlagClrOpen        Clear window on opening
  4214.               WFlagClrClose       Clear window on closing
  4215.               WFlagClrHide        Clear window on hiding
  4216.               WFlagRestore        Restore original when closed/hidden
  4217.               WFlagShowBrdr       Window has border
  4218.               WFlagWriteBrdr      Border can be overwritten
  4219.  
  4220.  
  4221.           The values for the required   flags should be added  together
  4222.           when assigning a value to Flags.
  4223.  
  4224.  
  4225.           WINDOW ZERO
  4226.  
  4227.               Window numbers 1 through  255  are available  for use  by
  4228.           your application program.   Window   zero is pre-defined  and
  4229.           represents the  entire  screen,  which  will  usually  be  80
  4230.           columns by 25 rows.
  4231.  
  4232.               Window zero is automatically made active at the start  of
  4233.           any program using the  ENHCON unit  and  the cursor and  text
  4234.           attribute will  be  those  in effect  when  the  program  was
  4235.           loaded.   It is  quite permissible  for window  zero   to  be
  4236.           selected in  order to use   the full screen as a window,  but
  4237.           no attempt should  be made to   close, hide,  or move  window
  4238.           zero; doing so will generate an error.
  4239.  
  4240.           -------------------------------------------------------------
  4241.  
  4242.           PROCEDURE DefineWindow (WindowID: BYTE; d: WindowDefinition);
  4243.  
  4244.               This procedure should  be  called to  define each  window
  4245.           that your application program requires.  A window  definition
  4246.           should be passed as  parameter  d and  the  window number  as
  4247.           WindowID.   The window number  specified may not be a  window
  4248.           that has already been defined and may not be zero.
  4249.  
  4250.               DefineWindow performs  several    error checks    on  the
  4251.           supplied definition before allowing  a new window.   Possible
  4252.           error   codes  are  01 (Invalid  co-ordinates),  02  (Invalid
  4253.           border  co-ordinates), 08 (Illegal window zero operation), 09
  4254.           (Window already  defined), and 10 (Out of memory).   The  two
  4255.           errors  relating  to  invalid    co-ordinates  require   some
  4256.           clarification.
  4257.  
  4258.           
  4259.           
  4260.                                       -70-  
  4261.               The co-ordinates (X1, Y1,   X2, and Y2)   must be  within
  4262.           range for the current display; X1 and Y1 must be less than or
  4263.           equal  to X2 and   Y2,  respectively.    The  minimum  window
  4264.           size   possible, therefore,  is  one row  by one  column  and
  4265.           failure to satisfy  these conditions results in error 01.  If
  4266.           the window has a border,   the co-ordinates specify the  top-
  4267.           left and bottom-right corners of the border and there must be
  4268.           at  least one row and one column  inside the border.  Failure
  4269.           to satisfy this  requirement results in  error code 02  being
  4270.           returned.
  4271.  
  4272.               Note that  DefineWindow  simply  assigns a  number  to  a
  4273.           specific window definition; it does not cause  the window  to
  4274.           be opened  on the display.
  4275.  
  4276.           -------------------------------------------------------------
  4277.  
  4278.           PROCEDURE OpenWindow (WindowID: BYTE);
  4279.  
  4280.               Calling this procedure causes a previously defined window
  4281.           to be opened  on the   screen.  The  window  number  required
  4282.           should  be passed as parameter  WindowID.  OpenWindow   calls
  4283.           Turbo  Pascal's Window procedure to set the co-ordinates of a
  4284.           new display  window  and all further output  is then sent  to
  4285.           that window instead of the whole screen.   The  top row   and
  4286.           left column  of a  window  are numbered as one.
  4287.  
  4288.               Opening a new window causes the  text attribute to be set
  4289.           to that specified by DefaultAttr in  the definition, and  the
  4290.           cursor size  and  hide  status  to  be  set  to  the   values
  4291.           found     in  DefaultCrsrSize  and    DefaultCrsrHide    (see
  4292.           Defining  a  window).  This process ensures that the  default
  4293.           cursor and text colors  are used whenever a window is opened.
  4294.  
  4295.               If the flag WFlagClrOpen is  set, the newly opened window
  4296.           is cleared to the   new text attribute.    If  this  flag  is
  4297.           clear  the current screen contents  are left in  place;  this
  4298.           gives rise to   a "see through" effect.   Most programs  will
  4299.           use the former option.
  4300.  
  4301.               WFlagShowBrdr controls whether a  border is drawn  around
  4302.           the new window.  Setting this flag to true causes the border,
  4303.           header, and footer to be written to the screen, as  described
  4304.           earlier.  If a  border is  enabled  the  flag  WFlagWriteBrdr
  4305.           is also  used.    A  value of false  causes the window's  co-
  4306.           ordinates to be set one row and column inside the border,  so
  4307.           that the area inside the  border scrolls, leaving the  border
  4308.           intact.    A true  value for this   flag  sets the   new  co-
  4309.           ordinates  on top  of the   border, allowing  the program  to
  4310.           write characters over part of the border.  The  latter option
  4311.           is useful for such things as menu option arrows.
  4312.  
  4313.  
  4314.           
  4315.           
  4316.                                       -71-  
  4317.               The cursor, whether visible or  hidden, is positioned  at
  4318.           the top-left corner  of the  new window.     With a  bordered
  4319.           window  this will be on   the top-left  border character   if
  4320.           WFlagWriteBrdr   is true  or one  column and  row inside  the
  4321.           border if WFlagWriteBrdr is false.  Finally, OpenWindow makes
  4322.           the new window active so  that further output to the  display
  4323.           is sent to the new window.
  4324.  
  4325.               Possible  error  codes  returned  by  OpenWindow  are  04
  4326.           (Window is already open), 08 (Illegal window zero operation),
  4327.           0A (Window not defined), and 10 (Out of memory).
  4328.  
  4329.           -------------------------------------------------------------
  4330.  
  4331.           PROCEDURE SelectWindow (WindowID: BYTE);
  4332.  
  4333.               This procedure  is  used to  move  from one  open  window
  4334.           to another.     The   required   window  number   should   be
  4335.           passed  as parameter WindowID.  SelectWindow does not  change
  4336.           the contents of  any window; it  simply allows movement  from
  4337.           one to another.
  4338.  
  4339.               The ENHCON unit  maintains a   record of the  cursor  and
  4340.           text attribute for  each open window.   When SelectWindow  is
  4341.           called, the  details of  the current  window are  saved,  the
  4342.           requested window   is made  active, and its  cursor and  text
  4343.           attribute are restored.   The cursor and text-attribute  save
  4344.           feature  ensures  that   when  a  window   is     re-selected
  4345.           everything  is  exactly  as   it  was  when  that  particular
  4346.           window was last used.
  4347.  
  4348.                It     is      important       to     realize       that
  4349.           DefaultAttr, DefaultCrsrSize,  and DefaultCrsrHide  are  used
  4350.           only  by  OpenWindow.  SelectWindow  automatically   restores
  4351.           whatever the last values  for  the window were; it  does  not
  4352.           restore  the defaults specified  in the window's  definition.
  4353.           If a  window  is   closed  and  then   later  re-opened,  the
  4354.           defaults  in its  definition  will be  used  once again.
  4355.  
  4356.               Possible error  codes  returned by  SelectWindow  are  05
  4357.           (Window is not open), 07  (Window is hidden), and 0A  (Window
  4358.           not defined).
  4359.  
  4360.           -------------------------------------------------------------
  4361.  
  4362.           PROCEDURE CloseWindow (WindowID: BYTE);
  4363.  
  4364.               This  procedure  performs  the    converse  function   to
  4365.           OpenWindow and removes a window from the screen.  The  window
  4366.           to close should be passed as parameter WindowID.
  4367.  
  4368.               Two flags in a   window's definition affect   the way  in
  4369.           which the window is  closed: WFlagClrClose and  WFlagRestore.
  4370.           
  4371.           
  4372.                                       -72-  
  4373.           If  both flags are clear the window is  considered closed but
  4374.           the area    of the  screen  it occupied  is  left  unchanged.
  4375.           Setting  WFlagClrClose causes the area previously occupied by
  4376.           the window to be  cleared;  the value in DefaultAttr is  used
  4377.           for this operation.   Finally,  if WFlagRestore is  set   the
  4378.           original screen   contents  are   restored.  This allows    a
  4379.           window to  be   "popped up"  temporarily   over  an  existing
  4380.           display.
  4381.  
  4382.               A list  of the  order  in which  windows were  opened  is
  4383.           maintaned by the unit.   If the window closed by  CloseWindow
  4384.           was not active, the currently  active window is not  changed.
  4385.           If the closed window was also  the current  window,  however,
  4386.           an  attempt is  made   to select whichever window was  active
  4387.           at the time  the closed   window was opened.   This  facility
  4388.           simplifies nested "pop up" menus,  and similar constructions,
  4389.           by avoiding  the need  to explicitly  re-select windows.
  4390.  
  4391.               Note that  if   it is   not  possible to   re-select  the
  4392.           previous window  (because it  has been   closed,  hidden,  or
  4393.           purged) an   error  will be   generated.     If you   do  not
  4394.           require this    "trace   back"  facility and  want  to  avoid
  4395.           errors, you should ensure that when  a window is closed it is
  4396.           not currently active.
  4397.  
  4398.               It is quite  permissible   to close  a   window which  is
  4399.           hidden. Doing so will   have no effect   on the display   and
  4400.           simply  throws away the stored text of the hidden window (see
  4401.           HideWindow).
  4402.  
  4403.               Possible error  codes returned    by CloseWindow  are  05
  4404.           (Window not open), 08  (Illegal window  zero operation),   0A
  4405.           (Window   not defined),  and 0B  (Cannot return  to  previous
  4406.           window).
  4407.  
  4408.           -------------------------------------------------------------
  4409.  
  4410.           PROCEDURE HideWindow (WindowID: BYTE); 
  4411.           PROCEDURE ShowWindow (WindowID: BYTE);
  4412.  
  4413.               A window  can be  removed  from the  display by   calling
  4414.           the CloseWindow  procedure, but  its contents  will be  lost.
  4415.           HideWindow allows a  window to  be removed  from the   screen
  4416.           but  saves  its contents  so that they may be restored  later
  4417.           by ShowWindow.
  4418.  
  4419.               Two flags in  a window's definition  affect the operation
  4420.           of   HideWindow   and    ShowWindow:      WFlagClrHide    and
  4421.           WFlagRestore.     The  former  works  in  a  similar  way  to
  4422.           WFlagClrClose with  CloseWindow, and the latter is identical.
  4423.           If both  flags  are  clear, HideWindow  stores  the  window's
  4424.           contents but leaves the screen unchanged.  If WFlagClrHide is
  4425.           set, the area  previously occupied by the  window is cleared.
  4426.           
  4427.           
  4428.                                       -73-  
  4429.           If WFlagRestore  is set,  the  original screen  contents  are
  4430.           restored.  If  the window to be  hidden is currently  active,
  4431.           then window zero is automatically selected.
  4432.  
  4433.               When a window is recalled with ShowWindow its entire area
  4434.           is re-drawn -  border, header,  footer,  and text.   If   the
  4435.           screen restore feature  is  in   use (i.e.  WFlagRestore   is
  4436.           set),  then ShowWindow updates the saved area of the original
  4437.           screen so  that CloseWindow will restore the correct text.
  4438.  
  4439.               Possible  error  codes    returned  by    HideWindow  and
  4440.           ShowWindow are 05 (Window not open), 08 (Illegal window  zero
  4441.           operation),  0A (Undefined window),  and 10 (Out of  memory).
  4442.           HideWindow can  also return  code 06 (Window already  hidden)
  4443.           and ShowWindow can  return 07 (Window not hidden).
  4444.  
  4445.           -------------------------------------------------------------
  4446.  
  4447.           PROCEDURE RelocateWindow (WindowID: BYTE; X, Y: BYTE); 
  4448.           PROCEDURE MoveWindow (WindowID:  BYTE;
  4449.                                 Direction: WindowMovement);
  4450.  
  4451.               These two routines allow a window to be re-positioned  on
  4452.           the screen.     Relocate   window   takes the    co-ordinates
  4453.           supplied  as parameters X  and Y  and uses  them as  the  new
  4454.           top-left corner  of the window.   The  new bottom-right   co-
  4455.           ordinates are   calculated automatically from   the  window's
  4456.           width and    height.     MoveWindow  takes a  value  of  type
  4457.           WindowMovement which specifies whether  the window should  be
  4458.           shifted up or  down   by one row  or left  or   right by  one
  4459.           column.  WindowMovement  is declared in  the interface as  an
  4460.           enumerated type:
  4461.  
  4462.             WindowMovement = (WMoveLeft,WMoveRight,WMoveUp,WMoveDown);
  4463.  
  4464.  
  4465.               Either routine  may be  called for  any window  which  is
  4466.           defined. If the window is  closed or hidden the changes  take
  4467.           effect when it  is next  opened  or  re-displayed.    If  the
  4468.           window    is  open  and    on  display,  the  move  is   made
  4469.           immediately.
  4470.  
  4471.               Possible  error  codes  are  01  (Invalid  co-ordinates),
  4472.           03 (Cannot move window in  specified direction), 08  (Illegal
  4473.           window zero operation),   0A  (Window   is  undefined),   and
  4474.           10  (Out  of memory).
  4475.  
  4476.           -------------------------------------------------------------
  4477.  
  4478.  
  4479.  
  4480.  
  4481.  
  4482.           
  4483.           
  4484.                                       -74-  
  4485.           PROCEDURE WriteWindow (s: ConsoleStr);
  4486.  
  4487.               Although  Turbo  Pascal's  standard  Write  and   WriteLn
  4488.           procedures can be  used to  write text  into  a window,  they
  4489.           do  cause  one problem: When an attempt is made  to fill  the
  4490.           window down to   the last  row and column,  the whole  window
  4491.           scrolls.
  4492.  
  4493.               WriteWindow is provided   to  avoid this   problem.   The
  4494.           string supplied as parameter s is written into the window  at
  4495.           the current  cursor position  and   using the   current  text
  4496.           attribute, but  the cursor is not moved, thus  preventing the
  4497.           window from   scrolling. In  addition, if the  string is  too
  4498.           long to fit between the current cursor position and the  edge
  4499.           of the window, it is truncated.
  4500.  
  4501.               The only error code that  can be returned by  WriteWindow
  4502.           is 10 (Out of memory).
  4503.  
  4504.           -------------------------------------------------------------
  4505.  
  4506.           FUNCTION CurrentWindow: BYTE;
  4507.  
  4508.               This function simply returns the identification number of
  4509.           the currently active  window.   If   CurrentWindow is  called
  4510.           before  any window has  been  opened,  it will  return  zero,
  4511.           indicating  that window zero (the whole screen) is active.
  4512.  
  4513.           -------------------------------------------------------------
  4514.  
  4515.           FUNCTION WindowStat (WindowID: BYTE): WindowStatus;
  4516.  
  4517.               WindowStatus  is  an  enumerated  type  declared  in  the
  4518.           interface section of the unit:
  4519.  
  4520.               WindowStatus = (Undefined, Closed, Hidden, Open, Active);
  4521.  
  4522.  
  4523.           A call  to WindowStat  returns the  status of  the  specified
  4524.           window. Note that window zero can only return Open or Active,
  4525.           because    it  cannot  be  closed  or  hidden,  or  have  its
  4526.           definition purged.
  4527.  
  4528.           -------------------------------------------------------------
  4529.  
  4530.           PROCEDURE PurgeWindow (WindowID: BYTE);
  4531.  
  4532.               PurgeWindow is used to remove a window's definition  from
  4533.           the ENHCON unit.    This   facility  will  not  be   required
  4534.           by  most programs, but is  provided for  two reasons:  First,
  4535.           if a  window must  be re-defined it   must be purged   before
  4536.           attempting to  call DefineWindow again.  Second, in  programs
  4537.           which use a great   many windows  and must  run  on a   small
  4538.           
  4539.           
  4540.                                       -75-  
  4541.           system it  may be necessary  to reclaim as much working store
  4542.           as possible  when a  window  is not  in  use.   (Each  window
  4543.           definition takes  up almost 200 bytes of  heap storage.)
  4544.  
  4545.               The  window  number    passed  to  PurgeWindow     should
  4546.           represent   a closed,  defined window,  and possible    error
  4547.           codes are 04   (Window  is open),  08 (Illegal  window   zero
  4548.           operation), and 0A  (Undefined window).
  4549.  
  4550.           -------------------------------------------------------------
  4551.  
  4552.           PROCEDURE GetWindowDef (WindowID: BYTE;
  4553.                                   VAR d:    WindowDefinition);
  4554.  
  4555.               GetWindowDef is unlikely  to be required  very often, but
  4556.           is included  for   completeness.      Calling this    routine
  4557.           causes  the definition of the specified window to be returned
  4558.           in record d.
  4559.  
  4560.               The  only  possible  error   code  for  GetWindowDef   is
  4561.           0A (Undefined window).
  4562.  
  4563.           -------------------------------------------------------------
  4564.  
  4565.           WINDOWS ERROR HANDLING
  4566.  
  4567.               The  ENHCON   unit   supports  a   comprehensive   error-
  4568.           handling system  for dealing  with  errors in  the  windowing
  4569.           routines.
  4570.  
  4571.               By default,  any  windows-related error  will   terminate
  4572.           the program with an appropriate message.  For example:
  4573.  
  4574.                           ENHCON unit run-time error 0A
  4575.                           Undefined window in OpenWindow
  4576.  
  4577.  
  4578.           The above message represents   an attempt to   open a  window
  4579.           which  has   not  been   defined.     The   global   variable
  4580.           EnhConHaltError can be set to  a program return code; when  a
  4581.           program is aborted due to an error this value is  passed back
  4582.           to the  operating  system.    (The program return   code   is
  4583.           accessible  from   a  batch   file   using ERRORLEVEL.)   The
  4584.           default value of EnhConHaltError is zero.
  4585.  
  4586.               Program termination  due   to error  can   be avoided  by
  4587.           setting the   global    variable   WindowCheck    to   false.
  4588.           Under   this configuration each windows routine sets a result
  4589.           code (very  much like the IOResult code in Turbo Pascal).   A
  4590.           program may call  the  function WindowResult after any  other
  4591.           windows routine in  order to  check   the   result   of   the
  4592.           operation.     The   windows    routine descriptions,  above,
  4593.           indicate the    possible  error   return    codes  from  each
  4594.           
  4595.           
  4596.                                       -76-  
  4597.           routine.   A value of zero   indicates that the  routine  was
  4598.           successful.
  4599.  
  4600.               The interface    section  of   ENHCON  defines    several
  4601.           constants which  specify  the  possible error  codes  in  the
  4602.           current version:
  4603.  
  4604.             Constant         Value    Error
  4605.             ConErrXY            01    Invalid co-ordinates
  4606.             ConErrBorderXY      02    Invalid border co-ordinates
  4607.             ConErrMove          03    Invalid direction
  4608.             ConErrOpen          04    Window is open
  4609.             ConErrClose         05    Window not open
  4610.             ConErrHidden        06    Window is hidden
  4611.             ConErrNotHidden     07    Window not hidden
  4612.             ConErrZero          08    Illegal window zero operation
  4613.             ConErrDefined       09    Window already defined
  4614.             ConErrUndefined     0A    Undefined window
  4615.             ConErrReturn        0B    Cannot return to previous window
  4616.             ConErrHeap          10    Out of memory
  4617.             ConErrHelpRead      11    Cannot access help file
  4618.             ConErrHelpInit      12    Help system already initialized
  4619.             ConErrNoHelpFile    13    Help file not found
  4620.             ConErrHelpFormat    14    Invalid format in help file
  4621.             ConErrHelpIndex     15    Invalid format for help index
  4622.             ConErrHelpInvalid   16    Help record invalid
  4623.             ConErrHelpStkFull   17    Help context stack full
  4624.             ConErrHelpStkEmpty  18    Help context stack empty
  4625.  
  4626.           Note that errors 11  through  18 hex. relate  to the  on-line
  4627.           help system, described in a later section of this manual.
  4628.  
  4629.           -------------------------------------------------------------
  4630.  
  4631.           FUNCTION WindowResult: BYTE;
  4632.  
  4633.               This function is used to obtain   the result code of  the
  4634.           last windows routine that  was called.   WindowResult returns
  4635.           zero  if the last  operation was  successful  or one  of  the
  4636.           error  codes listed above if it failed for some reason.
  4637.  
  4638.               All window-related routines cause  the result code to  be
  4639.           set. It is not  mandatory  to call  WindowResult after  every
  4640.           windowing operation, but errors will go undetected  if a call
  4641.           is not  made. As with Turbo  Pascal's own IOResult,   calling
  4642.           WindowResult   also resets  it to  zero.   A   call  to  this
  4643.           function when  internal    error checking  is  enabled  (i.e.
  4644.           WindowCheck  is true) serves no  useful purpose - errors will
  4645.           cause a program to abort before it can call WindowResult.
  4646.  
  4647.           -------------------------------------------------------------
  4648.  
  4649.  
  4650.           
  4651.           
  4652.                                       -77-  
  4653.           FUNCTION ConErrorMsg (ErrNum: BYTE): ConsoleStr;
  4654.  
  4655.               This function is  provided so that  application  programs
  4656.           can display  a suitable  error  message when  internal  error
  4657.           trapping   is disabled.   ConErrorMsg  should be   given  the
  4658.           result code  returned by WindowResult  or  the  help   error-
  4659.           handler  as   its   parameter ErrNum.   The returned   string
  4660.           will be one  of the error  messages listed above.
  4661.  
  4662.               A parameter value of zero  causes the string "Successful"
  4663.           to be returned and a code which  does not specify one of  the
  4664.           errors listed returns "Undefined error".
  4665.  
  4666.           -------------------------------------------------------------
  4667.  
  4668.           THE ON-LINE HELP SYSTEM
  4669.  
  4670.               The help  system relies  upon   the windows  routines  to
  4671.           provide "pop up"  displays and  will most likely  be used  in
  4672.           programs  which make  extensive use of  windows.  One  window
  4673.           identification  number  must be set  aside for the  exclusive
  4674.           use of the help system.
  4675.  
  4676.  
  4677.           CREATING THE HELP FILE
  4678.  
  4679.               The help system requires the help   file to be stored  on
  4680.           disk in a special format and a conversion utility is provided
  4681.           so  that the help text can be created using a standard  ASCII
  4682.           editor.
  4683.  
  4684.               The first line  of  the  text file must   contain just  a
  4685.           single number  that specifies  the  number of  help  sections
  4686.           required.  This number must be  in the range  1 through  255.
  4687.           Following lines  may contain any  comments you  wish to   add
  4688.           to  the file   for  future  reference; these comments do  not
  4689.           form  part of the  help text  and will  not be stored in  the
  4690.           final help file.
  4691.  
  4692.               The text for each help section follows the first line  or
  4693.           any comment  lines.    Each   section   must  start   with  a
  4694.           header   which includes  the section  number (represented  by
  4695.           "n") and name:
  4696.  
  4697.                           #n:Section name
  4698.  
  4699.  
  4700.           Note that  the "#"  symbol must  be in  the first  column and
  4701.           be immediately followed  by the section  number and a  colon.
  4702.           The text following  the colon  is used  as the  name for  the
  4703.           section and  will  appear in the help  index.  Section  names
  4704.           are limited to a maximum length of 30 characters and will  be
  4705.           truncated if longer.
  4706.           
  4707.           
  4708.                                       -78-  
  4709.               The text for  the section should  immediately follow  the
  4710.           header and be in the form that  you wish it to appear in  the
  4711.           help window.  There are three restrictions that apply to this
  4712.           text.  First, you should ensure  that no help text has a  "#"
  4713.           in the  first column,  as  this will  cause the    conversion
  4714.           program to  start a new  section. Second, no help section may
  4715.           have  more than 1,000 lines  of  text. Third, any line  which
  4716.           is too  long to fit across the help  window will be truncated
  4717.           when  it  is displayed;   you should ensure   that your  text
  4718.           fits within the margins of the intended window.
  4719.  
  4720.               The final section's text should be followed by a "#" on a
  4721.           new line.  You  may place  any  comments after this   marker;
  4722.           all  text following  it will   be ignored when   the file  is
  4723.           converted.   For example:
  4724.  
  4725.               3
  4726.               This text is a comment and will be ignored
  4727.               #1:First section
  4728.               This is the help text for section 1.
  4729.               This section will appear in the index as "First section."
  4730.               #2:Second section
  4731.               This is the help text for section 2.
  4732.               The index will show this section as "Second section."
  4733.               #3:Third & final
  4734.               This is the help test for section 3.
  4735.               The index will read "Third & final."
  4736.               #
  4737.               This text is also a comment
  4738.  
  4739.               Once you  have   created the   help   text required   you
  4740.           should convert it to a  format suitable for the  ENHCON  unit
  4741.           by  running  the HELPCONV  utility.  The  command syntax  for
  4742.           this program is
  4743.  
  4744.                   HELPCONV input-file output-file
  4745.  
  4746.           where input-file specifies the path and name of the text file
  4747.           to be processed.    The  output-file  parameter  is  optional
  4748.           and  may specify a path, a file  name, or both.   If no  path
  4749.           is   specified the  help file  will be  created in  the  same
  4750.           directory as the  input file; the file  name defaults  to the
  4751.           input file  name with  the extension changed to "HLP"  unless
  4752.           specified to the contrary.
  4753.  
  4754.               If the  text file   is converted  successfully,  HELPCONV
  4755.           will display a count  of the number   of lines processed  and
  4756.           the   number  of  help  sections.   If  the    text  file  is
  4757.           incorrectly formatted  in any way,  a format  error  will  be
  4758.           displayed, showing   the   line  number at  which  processing
  4759.           stopped.
  4760.  
  4761.  
  4762.           
  4763.           
  4764.                                       -79-  
  4765.               A format error can be due to any of the following:
  4766.  
  4767.           1.   The first  line does  not   specify the  number of  help
  4768.           sections or there are fewer help   sections in the file  than
  4769.           specified by this number.
  4770.  
  4771.           2.  A  section of  text does  not have  a properly  formatted
  4772.           header.  The "#"  symbol must be in  the first column and  be
  4773.           followed  by  the  section  number  and  a  colon,  with   no
  4774.           intervening blanks.
  4775.  
  4776.           3.   A section  is   missing or   listed  out of    sequence.
  4777.           Sections must be listed in ascending numerical order.
  4778.  
  4779.           4.   A section of help text is longer than 1,000 lines.
  4780.  
  4781.           5.  A line in the help  text has a "#" in  the first  column.
  4782.           If the help text  requires  this  symbol at the   start of  a
  4783.           line, precede it with a space.
  4784.  
  4785.           6.  There is no terminating "#" after the last help section.
  4786.  
  4787.  
  4788.               Once  the  help   conversion    utility   has  been   run
  4789.           successfully, the output file can be used by your program.
  4790.  
  4791.           -------------------------------------------------------------
  4792.  
  4793.           PROCEDURE HelpInitialize (h: HelpConfiguration);
  4794.  
  4795.               The following   type    declaration   appears   in    the
  4796.           interface section of the unit:
  4797.  
  4798.               HelpConfiguration = RECORD
  4799.                                     WindowID:           BYTE;
  4800.                                     HelpFileName:       ConsoleStr;
  4801.                                     X1, Y1, X2, Y2:     BYTE;
  4802.                                     NormalAttr,
  4803.                                     IndexAttr,
  4804.                                     SelectAttr:         BYTE;
  4805.                                     Border:             WindowBorder;
  4806.                                     BorderAttr:         BYTE;
  4807.                                     HdrText, FtrText:   ConsoleStr;
  4808.                                     HdrPos,  FtrPos:    WindowJustify;
  4809.                                     HdrAttr, FtrAttr:   BYTE;
  4810.                                     GeneralKey,
  4811.                                     ContextKey,
  4812.                                     LastHelpKey,
  4813.                                     MoveWindowKey:      CHAR;
  4814.                                     Flags:              BYTE;
  4815.                                   END;
  4816.  
  4817.  
  4818.           
  4819.           
  4820.                                       -80-  
  4821.           Several of the fields are the same   as those in a record  of
  4822.           type WindowDefinition.  Each field   is described in   detail
  4823.           below.    A variable of   type HelpConfiguration   should  be
  4824.           used to   set  the  fields to   the required   values,   then
  4825.           HelpInitialize  should  be called to set up the help unit.
  4826.  
  4827.               The number passed  in  WindowID  is used   as the  window
  4828.           number for the "pop up" help window.  This number must be  in
  4829.           the range 1 through 255, and your application  program should
  4830.           not  attempt    to  access   this  window  directly     (with
  4831.           DefineWindow, OpenWindow,  and so on).
  4832.  
  4833.               HelpFileName specifies the  path and   name of  the  file
  4834.           that holds the  help text.   Note  that the  string  supplied
  4835.           is  with reference to the  current directory at  the time  of
  4836.           the call  to HelpInitialize; if  the help file is not in  the
  4837.           current  directory,  HelpFileName   should  also   explicitly
  4838.           specify the correct drive and path.
  4839.  
  4840.               X1, Y1, X2, and  Y2  operate in  the same   way as for  a
  4841.           window definition and specify the  top-left and  bottom-right
  4842.           corners  of the required help  window.  A help window  always
  4843.           has a border,   so the available area  for help text will  be
  4844.           two columns and  two rows  less than  the total  area of  the
  4845.           window.
  4846.  
  4847.               NormalAttr specifies the text attribute that will be used
  4848.           to display  regular  help  text.   IndexAttr  and  SelectAttr
  4849.           control  the way  in which the index  will appear: The  first
  4850.           specifies the  text attribute for unselected index words  and
  4851.           the second specifies the attribute to be used to highlight  a
  4852.           particular entry.
  4853.  
  4854.               Border and  BorderAttr are  also identical  to a  regular
  4855.           window definition and specify  the characters and   attribute
  4856.           to be  used when displaying the help window's border.
  4857.  
  4858.               The unit  always defines  the   help window  as having  a
  4859.           border, as this  is the usual   requirement for  a "pop   up"
  4860.           window.  It  is possible to   prevent  a  border from   being
  4861.           displayed,  however, should this  be required  (such as  when
  4862.           using   a  help  window   that  occupies  the  full  screen).
  4863.           Setting all eight border  characters to a space (32  decimal,
  4864.           20 hex.)  or   setting BorderAttr  to   zero (MonoNone)  will
  4865.           accomplish this.   The  area that  would be  occupied by  the
  4866.           border cannot   be used,   so a   standard 80-by-25   display
  4867.           would have an  area of 78  columns by 23  rows available  for
  4868.           the help text.
  4869.  
  4870.               A help window  can have  a header and  footer, and  these
  4871.           fields are identical in operation  to the fields of  the same
  4872.           name in   a regular  window definition.   You  can disable  a
  4873.           header or footer by  setting HdrText  or  FtrText  (or  both)
  4874.           
  4875.           
  4876.                                       -81-  
  4877.           to a   null string.      The header and  footer  of  a   help
  4878.           window  are also  affected by  some other options.
  4879.  
  4880.               Four  fields    (GeneralKey,  ContextKey,    LastHelpKey,
  4881.           and MoveWindowKey) define which keys will be used to  control
  4882.           the help system.   They are described  in the section  titled
  4883.           Using help.
  4884.  
  4885.               Three flags  are  used by  the  help system,  and   these
  4886.           are defined as constants:
  4887.  
  4888.                           HFlagTitle      =  $04;
  4889.                           HFlagPageInd    =  $02;
  4890.                           HFlagPageText   =  $01;
  4891.  
  4892.           These values should  be added  together to  set the  required
  4893.           flags.
  4894.  
  4895.               Setting HFlagTitle  causes  the  name  of  the  currently
  4896.           displayed help section  to be  appended to  the header  text.
  4897.           If, for  example,  the  current  section   is  named    "File
  4898.           editing" and   the string   in HdrText is  'Help: ' then  the
  4899.           header would appear  as "Help:   File  editing".   When   the
  4900.           index is  on display the  string 'Index'  is used in place of
  4901.           the section name.    If HdrText  is a null   string then  the
  4902.           header will consist of just the section name.
  4903.  
  4904.               Setting HFlagPageInd causes up  and down page  indicators
  4905.           to be appended to  the footer text.    These indicators  take
  4906.           the form  of two arrows (character codes  24 and 25  decimal,
  4907.           18 and 19  hex.) which show whether there is more text  above
  4908.           or below the  current point.   If the  flag HFlagPageText  is
  4909.           also  set, then the  arrows are replaced with "PgUp," "PgDn,"
  4910.           or "PgUp/PgDn" as  appropriate. If FtrText is a null  string,
  4911.           then the  footer  will  consist  of  just  the  page  up/down
  4912.           indicators.
  4913.  
  4914.               Errors in the   help system are   handled differently  to
  4915.           those caused  by  a    windows routine    (see  Help    error
  4916.           handling,  below). Possible error  codes from  HelpInitialize
  4917.           are 01    (Invalid   co-ordinates),  02 (Invalid  border  co-
  4918.           ordinates), 08 (Illegal  attempt to  use  window  zero),   09
  4919.           (Window  already defined),  10  (Out  of memory), 11  (Cannot
  4920.           access help file),  12 (Help system  already initialized), 13
  4921.           (Help file not found),  14 (Format error in   help file),  15
  4922.           (Error in index entry).
  4923.  
  4924.           -------------------------------------------------------------
  4925.  
  4926.  
  4927.  
  4928.  
  4929.  
  4930.           
  4931.           
  4932.                                       -82-  
  4933.           INDEX LAYOUT
  4934.  
  4935.               It is not necessary  to specify  how the  index is to  be
  4936.           laid  out;  the    unit  does    this    automatically   when
  4937.           HelpInitialize  is called.   Index layout  is determined   by
  4938.           the  size  of   the   help window  and the   length  of   the
  4939.           longest section  name, and   ENHCON will fit as many  columns
  4940.           of index entries across the window as is possible.  The  help
  4941.           window must   be at least  wide enough to   hold the  longest
  4942.           section name.
  4943.  
  4944.  
  4945.           USING HELP
  4946.  
  4947.               After   a    call     to   HelpInitialize    has     been
  4948.           completed successfully,  the help  system is  ready for  use.
  4949.           ENHCON  monitors keyboard input for  the help key,  or  keys,
  4950.           by   linking into   the  standard ReadKey  function.     This
  4951.           means that  all console  input  should be by way  of  ReadKey
  4952.           if on-line  help is to be  available throughout the  program.
  4953.           On-line  help  will not  be  available during any input  with
  4954.           Read or ReadLn.
  4955.  
  4956.               All the editing routines in  the ENHCON unit use  ReadKey
  4957.           and will, therefore,  allow the help  system to be  activated
  4958.           during  an edit.
  4959.  
  4960.  
  4961.           GENERAL HELP
  4962.  
  4963.               The key  specified  in  the   GeneralKey  field  of   the
  4964.           help configuration will be trapped  by ReadKey and cause  the
  4965.           help index  to be  displayed.    The  first index  entry   is
  4966.           highlighted and  the cursor keys can then  be used to  select
  4967.           the required topic   from the  index.  If  the window is  not
  4968.           large enough to hold the section name for  every  topic,  the
  4969.           index  is automatically   split  into  pages.  The  following
  4970.           keys also have an effect while the index is displayed:
  4971.  
  4972.                   Tab             Move forward to next index entry
  4973.                   Shift-Tab       Move back to previous index entry
  4974.                   PgDn            Move to next index page
  4975.                   PgUp            Move to previous index page
  4976.                   Enter           Select topic
  4977.                   Esc             Leave help system
  4978.  
  4979.  
  4980.               When a specific topic has   been selected with the  Enter
  4981.           key, the  index  is  cleared  and  the    requested  text  is
  4982.           displayed.    Once again,  the text is   automatically  split
  4983.           into pages  if it is  too  long for the help window and   the
  4984.           PgUp, PgDn, Home,  and End   keys allow  movement around  the
  4985.           section's text.   Pressing  Escape causes  an immediate  exit
  4986.           
  4987.           
  4988.                                       -83-  
  4989.           from the help system;  pressing the general-help key  results
  4990.           in a  return  to the  index  so  that another  topic  may  be
  4991.           selected.
  4992.  
  4993.               When the help  system is   left by pressing  Escape,  the
  4994.           help window  is  closed  and the  original  screen  restored.
  4995.           ReadKey waits for another key to be pressed and returns  this
  4996.           key to the calling program  (unless help is requested  again,
  4997.           of course).  In  this way the use   of the   help  system  is
  4998.           completely transparent  to  the application program.
  4999.  
  5000.  
  5001.           CONTEXT-SENSITIVE HELP
  5002.  
  5003.               Many large  programs  now use  a  context-sensitive  help
  5004.           system, where requesting help will bring up the help  section
  5005.           appropriate to the current area, or context, of the  program.
  5006.           A code assigned to   the  ContextKey   field  of   the   help
  5007.           configuration   record specifies  the key that will  activate
  5008.           context-sensitive help.    If context-sensitive  help is  not
  5009.           required,  the value NUL should  be assigned to disable it.
  5010.  
  5011.               There is a  global variable called  HelpContext (of  type
  5012.           byte)  which  determines  the  current  context.     Whenever
  5013.           context-sensitive  help  is    requested,  the    value    in
  5014.           HelpContext  is used  to  jump straight to a particular  help
  5015.           section.  If HelpContext is set  to 5, pressing the  context-
  5016.           sensitive help key  will cause  the  help text for the  fifth
  5017.           section to be immediately displayed, bypassing the index.
  5018.  
  5019.               To implement  this  scheme effectively  requires  that  a
  5020.           value be assigned  to HelpContext whenever  the main  program
  5021.           enters an  area which must  have  a different  help  section.
  5022.           The value   assigned will  be used  as the  help section  for
  5023.           context-sensitive help until such  time as  a  new value   is
  5024.           assigned.   Setting HelpContext  to zero causes the  context-
  5025.           sensitive help key to display the  index, just as if  general
  5026.           help had been requested.    The index  is  also displayed  if
  5027.           HelpContext does not hold a valid section number  at the time
  5028.           help  is requested (e.g.  if HelpContext is  20 and  the help
  5029.           text only has 10 sections).
  5030.  
  5031.               Depending upon the program, it   may not be desirable  to
  5032.           have two separate  help  keys -  one  for  general help   and
  5033.           one    for  context-sensitive   help.    If  GeneralKey   and
  5034.           ContextKey are set  to the same value, pressing the  help key
  5035.           will display the  context-sensitive help as  usual.  If   the
  5036.           key is  pressed a  second  time (i.e. while   the help   text
  5037.           is visible),  the help  window  will switch to the index.
  5038.  
  5039.               It is also possible to disable general help by  assigning
  5040.           NUL to GeneralKey.   Under  these conditions it  will not  be
  5041.           possible to access the index unless context-sensitive help is
  5042.           
  5043.           
  5044.                                       -84-  
  5045.           called for when  HelpContext is set  to zero.    This  option
  5046.           could be used if it   is unlikely (or undesirable)  that  the
  5047.           user will  want to  "browse" through the help text.
  5048.  
  5049.           -------------------------------------------------------------
  5050.  
  5051.           PROCEDURE PushHelpContext (NewContext: BYTE); 
  5052.           PROCEDURE PopHelpContext;
  5053.  
  5054.               In many applications, a subroutine that requires  on-line
  5055.           help may be called from several different places in the  main
  5056.           program.   This requires  the assignment  of a  new value  to
  5057.           HelpContext upon entry  to the subroutine,  but the  original
  5058.           value must be restored when  control passes back to the  main
  5059.           program.
  5060.  
  5061.               The PushHelpContext and PopHelpContext procedures provide
  5062.           a simple way to achieve this by way of a help context  stack.
  5063.           A  call  to  PushHelpContext  causes  the  current  value  of
  5064.           HelpContext to be  saved on  the stack; the  value passed  as
  5065.           parameter  NewContext  is   then  assigned  to   HelpContext.
  5066.           Calling PopHelpContext causes the previously stored value  to
  5067.           be retrieved from the stack.
  5068.  
  5069.               In this way,  a commonly used  subroutine need only  call
  5070.           PushHelpContext with  its  appropriate  context  number  upon
  5071.           entry and make a call to PopHelpContext before returning.
  5072.  
  5073.               The stack has a maximum storage capacity of 127  numbers,
  5074.           which  should  be   adequate  for  even   the  most   complex
  5075.           application.  PushHelpContext can return an error code of  17
  5076.           (ConErrHelpStkFull) if the stack is full, and  PopHelpContext
  5077.           can return an error of  18 (ConErrHelpStkEmpty) if there  are
  5078.           no numbers currently stored on the stack.
  5079.  
  5080.               Note that calls to either procedure are simply ignored if
  5081.           the help system is not initialized.  This prevents calls from
  5082.           halting the application program if it is running without  on-
  5083.           line help.
  5084.  
  5085.           -------------------------------------------------------------
  5086.  
  5087.           LAST-HELP FACILITY
  5088.  
  5089.               One other way  to activate  the help system  is provided:
  5090.           If LastHelpKey  is  assigned  a  key    value,  pressing  the
  5091.           specified  key will cause the last help text  read to be  re-
  5092.           displayed.  It  does not matter whether the last help  access
  5093.           was from  the index  or   by way  of context-sensitive  help;
  5094.           whichever section was on   display when  the help window  was
  5095.           removed will be recalled.  The user  may then move around the
  5096.           text, press Escape  to leave  the help system,  or press  the
  5097.           general-help key to view the help index.
  5098.           
  5099.           
  5100.                                       -85-  
  5101.               Setting LastHelpKey  and GeneralKey   to the  same  value
  5102.           will cause  the specified  key   to activate  the   last-help
  5103.           facility.   A  second press of  the  key will  then cause   a
  5104.           switch to  the   index.  If  the last-help  facility  is  not
  5105.           required, LastHelpKey should  be assigned a value of NUL.
  5106.  
  5107.  
  5108.           MOVING THE HELP WINDOW
  5109.  
  5110.               The initial position of the help window is determined  by
  5111.           the co-ordinates    passed   to    HelpInitialize   in    the
  5112.           configuration record.   In some programs  it is desirable  to
  5113.           allow the window  to be moved by the user  - so that it  does
  5114.           not obscure other  text, for example.
  5115.  
  5116.               If a key code is assigned  to the MoveWindowKey field  of
  5117.           the configuration record,  the specified key  can be used  to
  5118.           toggle the cursor key  mode.   Whenever  the help  system  is
  5119.           activated  (by pressing  the general-help, context-help,   or
  5120.           last-help key),  the cursor keys allow selection of  an index
  5121.           entry.  After  presssing the move-window key the cursor  keys
  5122.           move the help window  around the screen, whether  the current
  5123.           help window   is  displaying   the index  or the  text for  a
  5124.           specific topic.  Pressing the move-window key a  second  time
  5125.           fixes  the window   in   its new  position   and returns  the
  5126.           cursor keys to normal.   If the user leaves the  help system,
  5127.           the  new position   for  the  window  is retained   so   that
  5128.           further calls to the  help system will use  the user's choice
  5129.           of window position.
  5130.  
  5131.               There  is  one  "special"  value  that  may  be  assigned
  5132.           to MoveWindowKey.     Assigning   the constant    HMoveScroll
  5133.           (character code  255 decimal,  FF   hex.) causes  the  scroll
  5134.           lock status to   be  used to determine  the cursor-key  mode.
  5135.           When scroll  lock is   on,  the cursor  keys   move the  help
  5136.           window; when scroll  lock is  off they allow movement  around
  5137.           the index as usual.
  5138.  
  5139.               Finally, if  MoveWindowKey is  assigned NUL  it will  not
  5140.           be possible for  the  help  window   to be  moved  from   its
  5141.           initial position.
  5142.  
  5143.           -------------------------------------------------------------
  5144.  
  5145.           PROCEDURE HelpReset;
  5146.  
  5147.               Most programs will initialize the   help system once  and
  5148.           then leave it  in place.   A  call to  HelpReset will   allow
  5149.           the  help  system to  be removed, should  this be  necessary.
  5150.           Possible reasons  would  be to  reclaim  memory space  or  to
  5151.           switch to a different  help file (an   advanced  user's  text
  5152.           in  place of  novice  text,  for example).   After  resetting
  5153.           the   help  system,   no  help    will   be  available  until
  5154.           
  5155.           
  5156.                                       -86-  
  5157.           HelpInitialize  is called to  install a new  help system.
  5158.  
  5159.               One possible use of this   technique is to separate  help
  5160.           into distinct modules.   An accounts   program, for  example,
  5161.           could    have  three  main  modules:    Accounts  receivable,
  5162.           accounts payable,   and  general ledger.   Three  help  files
  5163.           would be provided  on the   disk, one for  each  module,  and
  5164.           the entry  code  to  each module   would initialize the  help
  5165.           system with the appropriate file.  Requesting the help  index
  5166.           while in  accounts  receivable would  then  only   show  help
  5167.           sections relevant to that module; help relating to   accounts
  5168.           payable and the general ledger would not clutter the index.
  5169.  
  5170.               This method also allows  each  module to have  up to  255
  5171.           help sections (rather   than there  being  255  sections  for
  5172.           the  whole program), so long  as the help text can be  neatly
  5173.           divided into two or more separate indexes.
  5174.  
  5175.  
  5176.           HELP SYSTEM ERROR HANDLING
  5177.  
  5178.               By default, the  ENHCON unit   performs its own  internal
  5179.           error checking  on  the   help  system   and  will   abort  a
  5180.           program with  an appropriate message if an error occurs.  For
  5181.           example:
  5182.  
  5183.                   ENHCON unit run-time error 11
  5184.                   Cannot access help file in HelpInitialize
  5185.  
  5186.  
  5187.           The  interface  section   of  the   unit  defines   constants
  5188.           which represent  the   possible errors;   these  are   listed
  5189.           above  in  the Windows error handling section.
  5190.  
  5191.               The  description  of  HelpInitialize,  above,   indicates
  5192.           possible results  from  an  attempt to  initialize  the  help
  5193.           system.  Once   the help system  is set up,  an error may  be
  5194.           generated during a request for  help.      Such  errors   are
  5195.           limited     to         three         types:   ConErrHelpRead,
  5196.           ConErrHelpInvalid, and ConErrHeap.
  5197.  
  5198.               ConErrHelpRead is  generated  when   the help  file   has
  5199.           been corrupted.  It  usually indicates that  a record in  the
  5200.           file     is   missing   or   of   an      incorrect   format.
  5201.           ConErrHelpInvalid  indicates  that the unit's  record of  the
  5202.           help system is corrupt.  This error is likely if your program
  5203.           attempts to  manipulate  the  help    window  directly  (with
  5204.           OpenWindow,  HideWindow, etc.).     ConErrHeap  is  generated
  5205.           when a request for heap  storage fails, indicating  that  the
  5206.           system is out of free memory.
  5207.  
  5208.               In addition to  providing  internal error  checking,  the
  5209.           help system also allows  a program to  install its own  error
  5210.           
  5211.           
  5212.                                       -87-  
  5213.           handler  by way of the global procedural variable  HelpError.
  5214.           The  applicable declarations in the interface are as follows:
  5215.  
  5216.                   TYPE
  5217.                     HelpErrorProc  =  PROCEDURE (HErr: BYTE);
  5218.  
  5219.                   VAR
  5220.                     HelpError:  HelpErrorProc;
  5221.  
  5222.  
  5223.           HelpError is initialized  to the ENHCON's  own error  handler
  5224.           and if this is  all  that is  required  there is  no  need to
  5225.           make  any assignment to HelpError.
  5226.  
  5227.               A different    error   handler  can   be    installed  by
  5228.           writing    a  procedure  which  takes  a  single   byte-sized
  5229.           parameter  and   assigning  this   procedure  to   HelpError.
  5230.           Example:
  5231.  
  5232.                   {$F+}
  5233.                   PROCEDURE MyHelpError (ErrCode: BYTE);
  5234.  
  5235.                     BEGIN
  5236.                     .
  5237.                     .
  5238.                     END;
  5239.                   {$F-}
  5240.  
  5241.                   BEGIN  { Main code }
  5242.                     HelpError := MyHelpError;
  5243.                     .
  5244.                     .
  5245.                     .
  5246.  
  5247.  
  5248.           Note that the error-handling  routine must be  compiled as  a
  5249.           far subroutine; this  is   a requirement of   Turbo  Pascal's
  5250.           procedural variables.
  5251.  
  5252.               When an error  occurs in the  help system a  call is made
  5253.           to HelpReset to  reset the   help system.   Control  is  then
  5254.           passed  to  your own   error  hander,  which  may   take  any
  5255.           action  considered necessary for the particular program.  The
  5256.           automatic reset of the help system enables many errors to  be
  5257.           handled in a  simple manner.  If, for example,  the user  has
  5258.           removed the  diskette containing  the  help file,  the  error
  5259.           "Cannot access help  file" is generated.   The error  routine
  5260.           could open a window on the  screen, request the user to   re-
  5261.           insert   the    appropriate   diskette,    and   then    call
  5262.           HelpInitialize to re-load the help text.
  5263.  
  5264.  
  5265.  
  5266.           
  5267.           
  5268.                                       -88-  
  5269.               There  is  one  exception  to  the  automatic   reset-on-
  5270.           error process: If  HelpInitialize is   called when  the  help
  5271.           system  is  already initialized,  no reset  action will  take
  5272.           place.  When   your own  help-error handler is  called,   the
  5273.           help  system   will  be     reset   for  any   error   except
  5274.           ConErrHelpInit.
  5275.  
  5276.  
  5277.  
  5278.           RESTRICTIONS AND TEXTMODE
  5279.  
  5280.               There are  two restrictions   which  should be   observed
  5281.           when using  the  ENHCON  unit.     First,  the  unit    makes
  5282.           extensive use  of Turbo Pascal's Window procedure to set  the
  5283.           size of  windows on  the  screen.   You should  refrain  from
  5284.           calling Window (in the CRT unit)  directly and  control   all
  5285.           windowing on  the  screen  using  the appropriate routines in
  5286.           ENHCON.   Second,  extensive  use  is made  of  the  heap  to
  5287.           allocate window definitions, saved screen areas,  and so  on.
  5288.           The allocation routines   used  for this are  New,   Dispose,
  5289.           GetMem,   and    FreeMem,     and   in    accordance     with
  5290.           Borland's recommendations  your program  should not   try  to
  5291.           allocate and   de-allocate  heap storage  by using  Mark  and
  5292.           Release.
  5293.  
  5294.               By default, Turbo   Pascal  generates a   run-time  error
  5295.           when   a  program requests    heap   space  which   is    not
  5296.           available.     It   is possible,  however, to  disable   this
  5297.           feature by  implementing    your own    heap-error    handler
  5298.           (consult  your  reference   manual    for details).  If  your
  5299.           own program's error  routine causes  calls  to New or  GetMem
  5300.           which fail  to return  a nil  pointer, then  the ENHCON  unit
  5301.           generates its own error message (ConErrHeap, code 10   hex.).
  5302.           This allows  your  application  program  to  handle   out-of-
  5303.           memory errors in  any  way  you   wish, while  ensuring  that
  5304.           ENHCON  will always respond appropriately.
  5305.  
  5306.               Finally, you  should be  careful when  making a  call  to
  5307.           the TextMode  procedure.     Changing to  a   different  text
  5308.           display  mode causes ENHCON to dispose of all  window records
  5309.           and to reset   the help system.   If   you must change  modes
  5310.           within your program,   be sure to  re-define any windows  you
  5311.           might want  for  the  new mode  and  re-initialize  the  help
  5312.           system.
  5313.  
  5314.  
  5315.  
  5316.  
  5317.  
  5318.  
  5319.  
  5320.  
  5321.  
  5322.           
  5323.           
  5324.                                       -89-  
  5325.  
  5326.  
  5327.  
  5328.  
  5329.  
  5330.  
  5331.  
  5332.  
  5333.  
  5334.  
  5335.  
  5336.  
  5337.  
  5338.  
  5339.  
  5340.  
  5341.  
  5342.  
  5343.  
  5344.  
  5345.  
  5346.  
  5347.  
  5348.  
  5349.  
  5350.  
  5351.  
  5352.  
  5353.  
  5354.  
  5355.  
  5356.  
  5357.  
  5358.  
  5359.  
  5360.  
  5361.  
  5362.  
  5363.  
  5364.  
  5365.  
  5366.  
  5367.  
  5368.  
  5369.  
  5370.  
  5371.  
  5372.  
  5373.  
  5374.  
  5375.  
  5376.  
  5377.  
  5378.           
  5379.           
  5380.                                       -90-  
  5381.                                    APPENDIX A.
  5382.                                  UNIT INTERFACES 
  5383.           =============================================================
  5384.  
  5385.               This appendix summarizes the  interface section for  each
  5386.           unit in the library.
  5387.  
  5388.  
  5389.           UNIT STRINGS;
  5390.  
  5391.           {$L SUCASE}
  5392.           {$L SUTRIM}
  5393.           {$L SUPAD}
  5394.           {$L SUTRUNC}
  5395.           {$L SUCNVRT}
  5396.           {$L SUMISC}
  5397.  
  5398.           {$V-}
  5399.  
  5400.           INTERFACE
  5401.  
  5402.           TYPE
  5403.               FormatConfigRec =   RECORD
  5404.                                       Fill,
  5405.                                       Currency,
  5406.                                       Overflow,
  5407.                                       FracSep:    CHAR;
  5408.                                   END;
  5409.  
  5410.  
  5411.           CONST
  5412.               UCaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  5413.               LCaseLetters = 'abcdefghijklmnopqrstuvwxyz';
  5414.               Letters = UCaseLetters+LCaseLetters;
  5415.               DecDigits = '0123456789';
  5416.               HexDigits = '0123456789ABCDEF';
  5417.               OctDigits = '01234567';
  5418.               BinDigits = '01';
  5419.  
  5420.               { Format symbol record }
  5421.               FormatConfig: FormatConfigRec =
  5422.                               (Fill: '*';
  5423.                                Currency: '$';
  5424.                                Overflow: '?';
  5425.                                FracSep: '-');
  5426.  
  5427.  
  5428.  
  5429.  
  5430.  
  5431.  
  5432.  
  5433.  
  5434.           
  5435.           
  5436.                                       -91-  
  5437.           FUNCTION LoCase(ch: CHAR): CHAR;
  5438.           FUNCTION UpperCase(s: STRING): STRING;
  5439.           FUNCTION LowerCase(s: STRING): STRING;
  5440.           FUNCTION DuplChar(ch: CHAR; count: BYTE): STRING;
  5441.           FUNCTION DuplStr(s: STRING; count: BYTE): STRING;
  5442.           FUNCTION TrimL(s: STRING): STRING;
  5443.           FUNCTION TrimR(s: STRING): STRING;
  5444.           FUNCTION PadL(s: STRING; width: BYTE): STRING;
  5445.           FUNCTION PadR(s: STRING; width: BYTE): STRING;
  5446.           FUNCTION TruncL(s: STRING; width: BYTE): STRING;
  5447.           FUNCTION TruncR(s: STRING; width: BYTE): STRING;
  5448.           FUNCTION JustL(s: STRING; width: BYTE): STRING;
  5449.           FUNCTION JustR(s: STRING; width: BYTE): STRING;
  5450.           FUNCTION JustC(s: STRING; width: BYTE): STRING;
  5451.           FUNCTION Precede(s,target: STRING): STRING;
  5452.           FUNCTION Follow(s,target: STRING): STRING;
  5453.           FUNCTION Break(VAR s: STRING; d: STRING): STRING;
  5454.           FUNCTION Span(VAR s: STRING; d: STRING): STRING;
  5455.           FUNCTION Replace(s,srch,repl: STRING): STRING;
  5456.           FUNCTION Remove(s,srch: STRING): STRING;
  5457.           FUNCTION StripBit7(s: STRING): STRING;
  5458.           FUNCTION FileSpecDefault(s,path,name,extn: STRING): STRING;
  5459.           FUNCTION HexStr(n: WORD; count: BYTE): STRING;
  5460.           FUNCTION OctStr(n: WORD; count: BYTE): STRING;
  5461.           FUNCTION BinStr(n: WORD; count: BYTE): STRING;
  5462.           FUNCTION Format(n: REAL; form: STRING): STRING;
  5463.  
  5464.  
  5465.  
  5466.  
  5467.  
  5468.  
  5469.  
  5470.  
  5471.  
  5472.  
  5473.  
  5474.  
  5475.  
  5476.  
  5477.  
  5478.  
  5479.  
  5480.  
  5481.  
  5482.  
  5483.  
  5484.  
  5485.  
  5486.  
  5487.  
  5488.  
  5489.  
  5490.           
  5491.           
  5492.                                       -92-  
  5493.  
  5494.           UNIT MATH;
  5495.  
  5496.           {$N-}
  5497.  
  5498.           INTERFACE
  5499.  
  5500.           TYPE
  5501.               FLOAT = REAL;
  5502.  
  5503.  
  5504.           -------------------------------------------------------------
  5505.  
  5506.  
  5507.           UNIT MATH87;
  5508.  
  5509.           {$N+}
  5510.  
  5511.           INTERFACE
  5512.  
  5513.           TYPE
  5514.               FLOAT = EXTENDED;
  5515.  
  5516.  
  5517.  
  5518.  
  5519.  
  5520.  
  5521.  
  5522.  
  5523.  
  5524.  
  5525.  
  5526.  
  5527.  
  5528.  
  5529.  
  5530.  
  5531.  
  5532.  
  5533.  
  5534.  
  5535.  
  5536.  
  5537.  
  5538.  
  5539.  
  5540.  
  5541.  
  5542.  
  5543.  
  5544.  
  5545.  
  5546.           
  5547.           
  5548.                                       -93-  
  5549.           This section applies to both MATH and MATH87:
  5550.  
  5551.           FUNCTION  FahrToCent(FahrTemp: FLOAT): FLOAT;
  5552.           FUNCTION  CentToFahr(CentTemp: FLOAT): FLOAT;
  5553.           FUNCTION  KelvToCent(KelvTemp: FLOAT): FLOAT;
  5554.           FUNCTION  CentToKelv(CentTemp: FLOAT): FLOAT;
  5555.           PROCEDURE InchToFtIn(Inches: FLOAT; VAR ft,ins: FLOAT);
  5556.           FUNCTION  FtInToInch(ft,ins: FLOAT): FLOAT;
  5557.           FUNCTION  InchToYard(Inches: FLOAT): FLOAT;
  5558.           FUNCTION  YardToInch(Yards: FLOAT): FLOAT;
  5559.           FUNCTION  InchToMile(Inches: FLOAT): FLOAT;
  5560.           FUNCTION  MileToInch(Miles: FLOAT): FLOAT;
  5561.           FUNCTION  InchToNautMile(Inches: FLOAT): FLOAT;
  5562.           FUNCTION  NautMileToInch(NautMiles: FLOAT): FLOAT;
  5563.           FUNCTION  InchToMeter(Inches: FLOAT): FLOAT;
  5564.           FUNCTION  MeterToInch(Meters: FLOAT): FLOAT;
  5565.           FUNCTION  SqInchToSqFeet(SqInches: FLOAT): FLOAT;
  5566.           FUNCTION  SqFeetToSqInch(SqFeet: FLOAT): FLOAT;
  5567.           FUNCTION  SqInchToSqYard(SqInches: FLOAT): FLOAT;
  5568.           FUNCTION  SqYardToSqInch(SqYards: FLOAT): FLOAT;
  5569.           FUNCTION  SqInchToSqMile(SqInches: FLOAT): FLOAT;
  5570.           FUNCTION  SqMileToSqInch(SqMiles: FLOAT): FLOAT;
  5571.           FUNCTION  SqInchToAcre(SqInches: FLOAT): FLOAT;
  5572.           FUNCTION  AcreToSqInch(Acres: FLOAT): FLOAT;
  5573.           FUNCTION  SqInchToSqMeter(SqInches: FLOAT): FLOAT;
  5574.           FUNCTION  SqMeterToSqInch(SqMeters: FLOAT): FLOAT;
  5575.           FUNCTION  CuInchToCuFeet(CuInches: FLOAT): FLOAT;
  5576.           FUNCTION  CuFeetToCuInch(CuFeet: FLOAT): FLOAT;
  5577.           FUNCTION  CuInchToCuYard(CuInches: FLOAT): FLOAT;
  5578.           FUNCTION  CuYardToCuInch(CuYards: FLOAT): FLOAT;
  5579.           FUNCTION  CuInchToCuMeter(CuInches: FLOAT): FLOAT;
  5580.           FUNCTION  CuMeterToCuInch(CuMeters: FLOAT): FLOAT;
  5581.           FUNCTION  FluidOzToPint(FluidOz: FLOAT): FLOAT;
  5582.           FUNCTION  PintToFluidOz(Pints: FLOAT): FLOAT;
  5583.           FUNCTION  FluidOzToImpPint(FluidOz: FLOAT): FLOAT;
  5584.           FUNCTION  ImpPintToFluidOz(ImpPints: FLOAT): FLOAT;
  5585.           FUNCTION  FluidOzToGals(FluidOz: FLOAT): FLOAT;
  5586.           FUNCTION  GalsToFluidOz(Gals: FLOAT): FLOAT;
  5587.           FUNCTION  FluidOzToImpGals(FluidOz: FLOAT): FLOAT;
  5588.           FUNCTION  ImpGalsToFluidOz(ImpGals: FLOAT): FLOAT;
  5589.           FUNCTION  FluidOzToCuMeter(FluidOz: FLOAT): FLOAT;
  5590.           FUNCTION  CuMeterToFluidOz(CuMeters: FLOAT): FLOAT;
  5591.           PROCEDURE OunceToLbOz(Ounces: FLOAT; VAR lb,oz: FLOAT);
  5592.           FUNCTION  LbOzToOunce(lb,oz: FLOAT): FLOAT;
  5593.           FUNCTION  OunceToTon(Ounces: FLOAT): FLOAT;
  5594.           FUNCTION  TonToOunce(Tons: FLOAT): FLOAT;
  5595.           FUNCTION  OunceToLongTon(Ounces: FLOAT): FLOAT;
  5596.           FUNCTION  LongTonToOunce(LongTons: FLOAT): FLOAT;
  5597.           FUNCTION  OunceToGram(Ounces: FLOAT): FLOAT;
  5598.           FUNCTION  GramToOunce(Grams: FLOAT): FLOAT;
  5599.  
  5600.  
  5601.  
  5602.           
  5603.           
  5604.                                       -94-  
  5605.  
  5606.           UNIT TIME;
  5607.  
  5608.           {$V-}
  5609.  
  5610.           {$L DATE}
  5611.           {$L TIME}
  5612.  
  5613.  
  5614.           INTERFACE
  5615.  
  5616.           USES
  5617.               DOS;
  5618.  
  5619.           TYPE
  5620.               DateString =    STRING[9];
  5621.               TimeString =    STRING[13];
  5622.  
  5623.               DateRec =       RECORD
  5624.                                   M,D:    BYTE;
  5625.                                   Y:      WORD;
  5626.                               END;
  5627.  
  5628.               TimeRec =       RECORD
  5629.                                   H,M,S:  BYTE;
  5630.                               END;
  5631.  
  5632.  
  5633.  
  5634.           CONST
  5635.               DateFormNumeric  = 0;       TimeFormNormal       = 0;
  5636.               DateFormAlpha    = 1;       TimeFormNormalSec    = 1;
  5637.               DateFormMDY      = 2;       TimeFormShort        = 2;
  5638.               DateFormDMY      = 3;       TimeFormShortSec     = 3;
  5639.               DateFormLower    = 4;       TimeFormMilitary     = 4;
  5640.               DateFormZeroFill = 8;       TimeFormMilitarySec  = 5;
  5641.                                           TimeFormMilitaryHHMM = 6;
  5642.               FullDateFormMDY  = 0;
  5643.               FullDateFormDMY  = 1;
  5644.  
  5645.  
  5646.               TimeFormat:         BYTE        = TimeFormNormal;
  5647.               DateFormat:         BYTE        = DateFormNumeric;
  5648.               FullDateFormat:     BYTE        = FullDateFormMDY;
  5649.               TimeDelimiter:      CHAR        = ':';
  5650.               DateDelimiter:      CHAR        = '/';
  5651.               TimeParseDelims:    TimeString  = ':., '+#9;
  5652.               DateParseDelims:    DateString  = '/-., '+#9;
  5653.               TimeParseNow:       BOOLEAN     = FALSE;
  5654.               DateParseToDay:     BOOLEAN     = FALSE;
  5655.               DateParseCurYear:   BOOLEAN     = FALSE;
  5656.               DateParseCent21:    BYTE        = 0;
  5657.  
  5658.           
  5659.           
  5660.                                       -95-  
  5661.           PROCEDURE CombineDateTime(VAR DtTm: DateTime;
  5662.                                     Dt: DateRec; Tm: TimeRec);
  5663.           PROCEDURE SplitDateTime(DtTm: DateTime;
  5664.                               VAR Dt: DateRec; VAR Tm: TimeRec);
  5665.           PROCEDURE GetToDay(VAR Dt: DateRec);
  5666.           PROCEDURE GetTimeNow(VAR Tm: TimeRec);
  5667.           PROCEDURE GetDateTime(VAR DtTm: DateTime);
  5668.           FUNCTION  DateValid(Dt: DateRec): BOOLEAN;
  5669.           FUNCTION  TimeValid(Tm: TimeRec): BOOLEAN;
  5670.           FUNCTION  DateTimeValid(DtTm: DateTime): BOOLEAN;
  5671.           PROCEDURE WordToDate(w: WORD; VAR Dt: DateRec);
  5672.           FUNCTION  DateToWord(Dt: DateRec): WORD;
  5673.           FUNCTION  LeapYear(Y: WORD): BOOLEAN;
  5674.           FUNCTION  TimeAP(Tm: TimeRec): TimeString;
  5675.           PROCEDURE AdjustDate(VAR Dt: DateRec; n: INTEGER);
  5676.           PROCEDURE AdjustTime(VAR Tm: TimeRec; n: LongInt);
  5677.           PROCEDURE AdjustDateTime(VAR DtTm: DateTime; n: LongInt);
  5678.           PROCEDURE SetLastDay(VAR Dt: DateRec);
  5679.           FUNCTION  DayOfWeek(w: WORD): BYTE;
  5680.           FUNCTION  DayOfWeekStr(d: BYTE): DateString;
  5681.           FUNCTION  MonthStr(M: BYTE): DateString;
  5682.           FUNCTION  DayOfMonthStr(D: BYTE): DateString;
  5683.           FUNCTION  DateStr(Dt: DateRec): DateString;
  5684.           FUNCTION  FullDateStr(Dt: DateRec): STRING;
  5685.           FUNCTION  TimeStr(Tm: TimeRec): TimeString;
  5686.           FUNCTION  DateParse(s: STRING; VAR Dt: DateRec): BOOLEAN;
  5687.           FUNCTION  TimeParse(s: STRING; VAR Tm: TimeRec): BOOLEAN;
  5688.  
  5689.  
  5690.  
  5691.  
  5692.  
  5693.  
  5694.  
  5695.  
  5696.  
  5697.  
  5698.  
  5699.  
  5700.  
  5701.  
  5702.  
  5703.  
  5704.  
  5705.  
  5706.  
  5707.  
  5708.  
  5709.  
  5710.  
  5711.  
  5712.  
  5713.  
  5714.           
  5715.           
  5716.                                       -96-  
  5717.  
  5718.           UNIT STDERR;
  5719.  
  5720.           {$L STDERR}
  5721.  
  5722.           INTERFACE
  5723.  
  5724.           PROCEDURE WriteStdErr(s: STRING);
  5725.  
  5726.  
  5727.  
  5728.           -------------------------------------------------------------
  5729.  
  5730.  
  5731.  
  5732.           UNIT CRTCLERR;
  5733.  
  5734.           INTERFACE
  5735.  
  5736.           TYPE
  5737.               ErrorString =   STRING[20];
  5738.  
  5739.  
  5740.           PROCEDURE CriticalErrorDOS;
  5741.           PROCEDURE CriticalErrorTP;
  5742.           PROCEDURE CriticalErrorOwn(ErrAddr: POINTER);
  5743.           FUNCTION  CriticalErrorMsg(n: BYTE): ErrorString;
  5744.  
  5745.  
  5746.  
  5747.  
  5748.  
  5749.  
  5750.  
  5751.  
  5752.  
  5753.  
  5754.  
  5755.  
  5756.  
  5757.  
  5758.  
  5759.  
  5760.  
  5761.  
  5762.  
  5763.  
  5764.  
  5765.  
  5766.  
  5767.  
  5768.  
  5769.  
  5770.           
  5771.           
  5772.                                       -97-  
  5773.           UNIT ENHCON;
  5774.  
  5775.           {$V-}
  5776.  
  5777.           {$L CRTVDU}
  5778.           {$L CRTKB}
  5779.  
  5780.           INTERFACE
  5781.  
  5782.           USES
  5783.               DOS,CRT,STRINGS,TIME;
  5784.  
  5785.  
  5786.           TYPE
  5787.               CharSet     =   SET OF CHAR;
  5788.               ConsoleStr  =   STRING[80];
  5789.  
  5790.               SignalErrorProc  =  PROCEDURE(width: BYTE);
  5791.  
  5792.               EditFormatRec =
  5793.                   RECORD
  5794.                       Attribute:      BYTE;
  5795.                       StartChar,
  5796.                       EndChar:        CHAR;
  5797.                       MarkerAttr:     BYTE;
  5798.                       AllowChars,
  5799.                       ExitKeys:       CharSet;
  5800.                       EditKey,
  5801.                       RestoreKey,
  5802.                       AbortKey:       CHAR;
  5803.                       NumFormat:      STRING[12];
  5804.                       SignalError:    SignalErrorProc;
  5805.                       Flags:          WORD;
  5806.                   END;
  5807.  
  5808.  
  5809.               WindowStatus    = (Undefined,Closed,Hidden,Open,Active);
  5810.               WindowBorder    = ARRAY[1..8] OF CHAR;
  5811.               WindowJustify   = (WJustLeft,WJustCenter,WJustRight);
  5812.               WindowMovement  = (WMoveLeft,WMoveRight,
  5813.                                  WMoveUp,WMoveDown);
  5814.  
  5815.  
  5816.  
  5817.  
  5818.  
  5819.  
  5820.  
  5821.  
  5822.  
  5823.  
  5824.  
  5825.  
  5826.           
  5827.           
  5828.                                       -98-  
  5829.               WindowDefinition =
  5830.                   RECORD
  5831.                       X1, Y1, X2, Y2:     BYTE;
  5832.                       DefaultAttr:        BYTE;
  5833.                       DefaultCrsrHide:    BOOLEAN;
  5834.                       DefaultCrsrSize:    WORD;
  5835.                       Border:             WindowBorder;
  5836.                       BorderAttr:         BYTE;
  5837.                       HdrText, FtrText:   ConsoleStr;
  5838.                       HdrAttr, FtrAttr:   BYTE;
  5839.                       HdrPos,  FtrPos:    WindowJustify;
  5840.                       Flags:              BYTE;
  5841.                   END;
  5842.  
  5843.               HelpConfiguration =
  5844.                   RECORD
  5845.                       WindowID:           BYTE;
  5846.                       HelpFileName:       ConsoleStr;
  5847.                       X1, Y1, X2, Y2:     BYTE;
  5848.                       NormalAttr,
  5849.                       IndexAttr,
  5850.                       SelectAttr:         BYTE;
  5851.                       Border:             WindowBorder;
  5852.                       BorderAttr:         BYTE;
  5853.                       HdrText, FtrText:   ConsoleStr;
  5854.                       HdrPos,  FtrPos:    WindowJustify;
  5855.                       HdrAttr, FtrAttr:   BYTE;
  5856.                       GeneralKey,
  5857.                       ContextKey,
  5858.                       LastHelpKey,
  5859.                       MoveWindowKey:      CHAR;
  5860.                       Flags:              BYTE;
  5861.                   END;
  5862.  
  5863.               HelpErrorProc   = PROCEDURE(HErr: BYTE);
  5864.  
  5865.           CONST
  5866.                                               WFlagClrOpen    = $01;
  5867.               EdFlagTrimL     = $0001;        WFlagClrClose   = $02;
  5868.               EdFlagTrimR     = $0002;        WFlagClrHide    = $04;
  5869.               EdFlagPadL      = $0004;        WFlagRestore    = $08;
  5870.               EdFlagPadR      = $0008;        WFlagShowBrdr   = $10;
  5871.               EdFlagUpper     = $0010;        WFlagWriteBrdr  = $20;
  5872.  
  5873.               EdFlagFlushKB   = $0100;        HFlagPageText   = $01;
  5874.               EdFlagInsert    = $0200;        HFlagPageInd    = $02;
  5875.               EdFlagForceIns  = $0400;        HFlagTitle      = $04;
  5876.               EdFlagInsStat   = $0800;
  5877.               EdFlagFirstClr  = $1000;        WCrsrDefault    = $FF00;
  5878.               EdFlagEdKeyExit = $2000;        WCrsrLine       = $FE00;
  5879.               EdFlagHideCrsr  = $4000;        WCrsrBlock      = $FD00;
  5880.  
  5881.                                               HMoveScroll     = #$FF;
  5882.           
  5883.           
  5884.                                       -99-  
  5885.               WBorder1:       WindowBorder  =
  5886.                   (#218,#196,#191,#179,#217,#196,#192,#179);
  5887.               WBorder2:       WindowBorder  =
  5888.                   (#201,#205,#187,#186,#188,#205,#200,#186);
  5889.               WBorderV1H2:    WindowBorder  =
  5890.                   (#213,#205,#184,#179,#190,#205,#212,#179);
  5891.               WBorderH1V2:    WindowBorder  =
  5892.                   (#214,#196,#183,#186,#189,#196,#211,#186);
  5893.  
  5894.               MonoNone        = $00;
  5895.               MonoUnderline   = $01;
  5896.               MonoNormal      = $07;
  5897.               MonoIntenseUL   = $09;
  5898.               MonoIntense     = $0F;
  5899.               MonoReverse     = $70;
  5900.  
  5901.  
  5902.           { ASCII control codes }
  5903.  
  5904.               NUL = #$00;     { Null }
  5905.               SOH = #$01;     { Start Of Header }
  5906.               STX = #$02;     { Start of Text }
  5907.               ETX = #$03;     { End of Text }
  5908.               EOT = #$04;     { End Of Transmission }
  5909.               ENQ = #$05;     { Enquiry }
  5910.               ACK = #$06;     { Acknowledge }
  5911.               BEL = #$07;     { Bell }
  5912.               BS  = #$08;     { Backspace }
  5913.               HT  = #$09;     { Horizontal Tab }
  5914.               LF  = #$0A;     { Line Feed }
  5915.               VT  = #$0B;     { Vertical Tab }
  5916.               FF  = #$0C;     { Form Feed }
  5917.               CR  = #$0D;     { Carriage Return }
  5918.               SO  = #$0E;     { Shift Out }
  5919.               SI  = #$0F;     { Shift In }
  5920.               DLE = #$10;     { Data Link Escape }
  5921.               DC1 = #$11;     { Device Control 1 }
  5922.               DC2 = #$12;     { Device Control 2 }
  5923.               DC3 = #$13;     { Device Control 3 }
  5924.               DC4 = #$14;     { Device Control 4 }
  5925.               NAK = #$15;     { Negative Acknowledge }
  5926.               SYN = #$16;     { Synchronous idle }
  5927.               ETB = #$17;     { End Transmission Block }
  5928.               CAN = #$18;     { Cancel }
  5929.               EM  = #$19;     { End of Medium }
  5930.               SUB = #$1A;     { Substitute }
  5931.               ESC = #$1B;     { Escape }
  5932.               FS  = #$1C;     { File Separator }
  5933.               GS  = #$1D;     { Group Separator }
  5934.               RS  = #$1E;     { Record Separator }
  5935.               US  = #$1F;     { Unit Separator }
  5936.               DEL = #$7F;     { Delete }
  5937.  
  5938.           
  5939.           
  5940.                                       -100-  
  5941.               PoundSign = #$9C;
  5942.  
  5943.               StandardChars = [#32..#126];
  5944.  
  5945.               KeyIns   = #$80;
  5946.               KeyDel   = #$81;
  5947.               KeyUp    = #$82;
  5948.               KeyDown  = #$83;
  5949.               KeyLeft  = #$84;         KeyCLeft    = #$8A;
  5950.               KeyRight = #$85;         KeyCRight   = #$8B;
  5951.               KeyHome  = #$86;         KeyCHome    = #$8C;
  5952.               KeyEnd   = #$87;         KeyCEnd     = #$8D;
  5953.               KeyPgUp  = #$88;         KeyCPgUp    = #$8E;
  5954.               KeyPgDn  = #$89;         KeyCPgDn    = #$8F;
  5955.  
  5956.               KeyA0    = #$90;         KeyAHyphen  = #$9A;
  5957.               KeyA1    = #$91;         KeyAEquals  = #$9B;
  5958.               KeyA2    = #$92;
  5959.               KeyA3    = #$93;
  5960.               KeyA4    = #$94;         KeySTab     = #$9D;
  5961.               KeyA5    = #$95;         KeyCPrtSc   = #$9E;
  5962.               KeyA6    = #$96;
  5963.               KeyA7    = #$97;
  5964.               KeyA8    = #$98;
  5965.               KeyA9    = #$99;
  5966.  
  5967.               KeyF1    = #$A0;         KeySF1  = #$B0;
  5968.               KeyF2    = #$A1;         KeySF2  = #$B1;
  5969.               KeyF3    = #$A2;         KeySF3  = #$B2;
  5970.               KeyF4    = #$A3;         KeySF4  = #$B3;
  5971.               KeyF5    = #$A4;         KeySF5  = #$B4;
  5972.               KeyF6    = #$A5;         KeySF6  = #$B5;
  5973.               KeyF7    = #$A6;         KeySF7  = #$B6;
  5974.               KeyF8    = #$A7;         KeySF8  = #$B7;
  5975.               KeyF9    = #$A8;         KeySF9  = #$B8;
  5976.               KeyF10   = #$A9;         KeySF10 = #$B9;
  5977.  
  5978.               KeyCF1   = #$C0;         KeyAF1  = #$D0;
  5979.               KeyCF2   = #$C1;         KeyAF2  = #$D1;
  5980.               KeyCF3   = #$C2;         KeyAF3  = #$D2;
  5981.               KeyCF4   = #$C3;         KeyAF4  = #$D3;
  5982.               KeyCF5   = #$C4;         KeyAF5  = #$D4;
  5983.               KeyCF6   = #$C5;         KeyAF6  = #$D5;
  5984.               KeyCF7   = #$C6;         KeyAF7  = #$D6;
  5985.               KeyCF8   = #$C7;         KeyAF8  = #$D7;
  5986.               KeyCF9   = #$C8;         KeyAF9  = #$D8;
  5987.               KeyCF10  = #$C9;         KeyAF10 = #$D9;
  5988.  
  5989.  
  5990.  
  5991.  
  5992.  
  5993.  
  5994.           
  5995.           
  5996.                                       -101-  
  5997.               KeyAA    = #$E1;         KeyAP  = #$F0;
  5998.               KeyAB    = #$E2;         KeyAQ  = #$F1;
  5999.               KeyAC    = #$E3;         KeyAR  = #$F2;
  6000.               KeyAD    = #$E4;         KeyAS  = #$F3;
  6001.               KeyAE    = #$E5;         KeyAT  = #$F4;
  6002.               KeyAF    = #$E6;         KeyAU  = #$F5;
  6003.               KeyAG    = #$E7;         KeyAV  = #$F6;
  6004.               KeyAH    = #$E8;         KeyAW  = #$F7;
  6005.               KeyAI    = #$E9;         KeyAX  = #$F8;
  6006.               KeyAJ    = #$EA;         KeyAY  = #$F9;
  6007.               KeyAK    = #$EB;         KeyAZ  = #$FA;
  6008.               KeyAL    = #$EC;
  6009.               KeyAM    = #$ED;
  6010.               KeyAN    = #$EE;
  6011.               KeyAO    = #$EF;
  6012.  
  6013.  
  6014.           { Error codes }
  6015.  
  6016.               ConErrXY            = $01;
  6017.               ConErrBorderXY      = $02;
  6018.               ConErrMove          = $03;
  6019.               ConErrOpen          = $04;
  6020.               ConErrClosed        = $05;
  6021.               ConErrHidden        = $06;
  6022.               ConErrNotHidden     = $07;
  6023.               ConErrZero          = $08;
  6024.               ConErrDefined       = $09;
  6025.               ConErrUndefined     = $0A;
  6026.               ConErrReturn        = $0B;
  6027.               ConErrHeap          = $10;
  6028.               ConErrHelpRead      = $11;
  6029.               ConErrHelpInit      = $12;
  6030.               ConErrNoHelpFile    = $13;
  6031.               ConErrHelpFormat    = $14;
  6032.               ConErrHelpIndex     = $15;
  6033.               ConErrHelpInvalid   = $16;
  6034.               ConErrHelpStkFull   = $17;
  6035.               ConErrHelpStkEmpty  = $18;
  6036.  
  6037.  
  6038.               InsKeyEnable:       BOOLEAN = FALSE;
  6039.               CursorInsert:       BOOLEAN = FALSE;
  6040.               WindowCheck:        BOOLEAN = TRUE;
  6041.               EnhConHaltError:    WORD    = 0;
  6042.               HelpContext:        BYTE    = 0;
  6043.  
  6044.           VAR
  6045.               HelpError:  HelpErrorProc;
  6046.  
  6047.  
  6048.  
  6049.  
  6050.           
  6051.           
  6052.                                       -102-  
  6053.           FUNCTION  ColorDisplay: BOOLEAN;
  6054.           FUNCTION  MaxCursorSize: BYTE;
  6055.           PROCEDURE SetCursor(size: WORD);
  6056.           FUNCTION  GetCursor: WORD;
  6057.           PROCEDURE HideCursor(hide: BOOLEAN);
  6058.           FUNCTION  CursorHidden: BOOLEAN;
  6059.           PROCEDURE OrigCursor;
  6060.           PROCEDURE LineCursor;
  6061.           PROCEDURE BlockCursor;
  6062.           FUNCTION  GetDisplayPage: BYTE;
  6063.           FUNCTION  GetDisplayBase: WORD;
  6064.           PROCEDURE GetMaxXY(VAR x,y: BYTE);
  6065.           PROCEDURE FlushKB;
  6066.           FUNCTION  CapsLock: BOOLEAN;
  6067.           FUNCTION  NumLock: BOOLEAN;
  6068.           FUNCTION  ScrollLock: BOOLEAN;
  6069.           FUNCTION  InsertLock: BOOLEAN;
  6070.           PROCEDURE ForceInsert(Ins: BOOLEAN);
  6071.           PROCEDURE StdSignalError(width: BYTE);
  6072.           FUNCTION  EditString(form: EditFormatRec;
  6073.                                VAR s: STRING; width: BYTE): CHAR;
  6074.           FUNCTION  EditInt(form: EditFormatRec;
  6075.                                VAR i: LongInt; min,max: LongInt): CHAR;
  6076.           FUNCTION  EditReal(form: EditFormatRec;
  6077.                                VAR r: REAL; min,max: REAL): CHAR;
  6078.           FUNCTION  EditDate(form: EditFormatRec;
  6079.                                VAR Dt: DateRec): CHAR;
  6080.           FUNCTION  EditTime(form: EditFormatRec;
  6081.                                VAR Tm: TimeRec): CHAR;
  6082.           FUNCTION  WindowResult: BYTE;
  6083.           FUNCTION  ConErrorMsg(ErrNum: BYTE): ConsoleStr;
  6084.           PROCEDURE GetWindowDef(WindowID: BYTE;
  6085.                                  VAR d: WindowDefinition);
  6086.           FUNCTION  WindowStat(WindowID: BYTE): WindowStatus;
  6087.           FUNCTION  CurrentWindow: BYTE;
  6088.           PROCEDURE DefineWindow(WindowID: BYTE; d: WindowDefinition);
  6089.           PROCEDURE PurgeWindow(WindowID: BYTE);
  6090.           PROCEDURE OpenWindow(WindowID: BYTE);
  6091.           PROCEDURE SelectWindow(WindowID: BYTE);
  6092.           PROCEDURE CloseWindow(WindowID: BYTE);
  6093.           PROCEDURE HideWindow(WindowID: BYTE);
  6094.           PROCEDURE ShowWindow(WindowID: BYTE);
  6095.           PROCEDURE RelocateWindow(WindowID: BYTE; X,Y: BYTE);
  6096.           PROCEDURE MoveWindow(WindowID: BYTE;
  6097.                                Direction: WindowMovement);
  6098.           PROCEDURE WriteWindow(s: ConsoleStr);
  6099.           PROCEDURE HelpReset;
  6100.           PROCEDURE PushHelpContext(NewContext: BYTE);
  6101.           PROCEDURE PopHelpContext;
  6102.           PROCEDURE HelpInitialize(h: HelpConfiguration);
  6103.           PROCEDURE TextMode(Mode: WORD);
  6104.           FUNCTION  ReadKey: CHAR;
  6105.  
  6106.           
  6107.           
  6108.                                       -103-  
  6109.  
  6110.  
  6111.  
  6112.  
  6113.  
  6114.  
  6115.  
  6116.  
  6117.  
  6118.  
  6119.  
  6120.  
  6121.  
  6122.  
  6123.  
  6124.  
  6125.  
  6126.  
  6127.  
  6128.  
  6129.  
  6130.  
  6131.  
  6132.  
  6133.  
  6134.  
  6135.  
  6136.  
  6137.  
  6138.  
  6139.  
  6140.  
  6141.  
  6142.  
  6143.  
  6144.  
  6145.  
  6146.  
  6147.  
  6148.  
  6149.  
  6150.  
  6151.  
  6152.  
  6153.  
  6154.  
  6155.  
  6156.  
  6157.  
  6158.  
  6159.  
  6160.  
  6161.  
  6162.           
  6163.           
  6164.                                       -104-  
  6165.                                    APPENDIX B.
  6166.                                 CODE DEPENDENCIES 
  6167.           =============================================================
  6168.  
  6169.           TPU DEPENDENCIES
  6170.  
  6171.               Library unit:       Uses units:
  6172.  
  6173.               STRINGS             DOS
  6174.               MATH/MATH87         No dependencies
  6175.               TIME                DOS, STRINGS
  6176.               STDERR              No dependencies
  6177.               CRTCLERR            DOS
  6178.               ENHCON              DOS, CRT, STRINGS, TIME
  6179.  
  6180.  
  6181.  
  6182.           ASSEMBLER MODULE DEPENDENCIES
  6183.  
  6184.               Library unit:       Requires OBJ modules:
  6185.  
  6186.               STRINGS             SUCASE, SUTRIM, SUPAD, SUTRUNC,
  6187.                                   SUCNVRT, SUMISC
  6188.               MATH/MATH87         No assembler modules
  6189.               TIME                DATE, TIME
  6190.               STDERR              STDERR
  6191.               CRTCLERR            No assembler modules
  6192.               ENHCON              CRTVDU, CRTKB
  6193.  
  6194.  
  6195.  
  6196.           OPERATING SYSTEM & FIRMWARE DEPENDENCIES
  6197.  
  6198.               ENHCON  unit  requires  compatibility  at  BIOS  services
  6199.           level.    All  other  units  require  only  compatibility  at
  6200.           operating-system level for DOS 2.0 or greater.
  6201.  
  6202.  
  6203.           HELP CONVERSION UTILITY DEPENDENCY
  6204.  
  6205.               The following   units   are   required   in   order    to
  6206.           recompile HELPCONV:
  6207.  
  6208.                   DOS, STDERR, CRTCLERR, STRINGS
  6209.  
  6210.  
  6211.  
  6212.  
  6213.  
  6214.  
  6215.  
  6216.  
  6217.  
  6218.           
  6219.           
  6220.                                       -105-  
  6221.  
  6222.  
  6223.  
  6224.  
  6225.  
  6226.  
  6227.  
  6228.  
  6229.  
  6230.  
  6231.  
  6232.  
  6233.  
  6234.  
  6235.  
  6236.  
  6237.  
  6238.  
  6239.  
  6240.  
  6241.  
  6242.  
  6243.  
  6244.  
  6245.  
  6246.  
  6247.  
  6248.  
  6249.  
  6250.  
  6251.  
  6252.  
  6253.  
  6254.  
  6255.  
  6256.  
  6257.  
  6258.  
  6259.  
  6260.  
  6261.  
  6262.  
  6263.  
  6264.  
  6265.  
  6266.  
  6267.  
  6268.  
  6269.  
  6270.  
  6271.  
  6272.  
  6273.  
  6274.           
  6275.           
  6276.                                       -106-  
  6277.                                    APPENDIX C.
  6278.                                 REVISION HISTORY 
  6279.           =============================================================
  6280.  
  6281.  
  6282.           VERSION 1.0, August 1991
  6283.  
  6284.               The name  of this  library  package became  Turbo  Pascal
  6285.           Library when the code  was released to  the public domain  in
  6286.           August 1991.
  6287.  
  6288.  
  6289.           VERSION 1.1, December 1991
  6290.  
  6291.               The most noticeable change is the integration of  ENHCRT,
  6292.           WINDOWS, and HELP  into ENHCON,  putting all  console-related
  6293.           routines together  into  one  unit.   Programs  written  with
  6294.           version 1.0 of Turbo Pascal  Library can now have  references
  6295.           to the  original three  units replaced  with a  single  "USES
  6296.           ENHCON;" declaration.
  6297.  
  6298.               The error codes for the old HELP unit have been  changed,
  6299.           to enable  them to  be  integrated with  the  windows-related
  6300.           errors. All WErr and HErr  codes should be replaced with  the
  6301.           appropriate ConErr  code.   The  function  WindowErrorMsg  no
  6302.           longer exists; you  should now use  the ConErrorMsg  function
  6303.           instead.  The two variables WindowHaltError and HelpHaltError
  6304.           have been replaced with the single variable EnhConHaltError.
  6305.  
  6306.               After using the help system in version 1.0, ReadKey would
  6307.           return the  value of  the help  key to  the calling  program.
  6308.           This is no longer the case; ReadKey waits for another key  to
  6309.           be pressed before returning.
  6310.  
  6311.               A  bug  which  prevented  the  help  system  from   being
  6312.           activated during an edit routine has been fixed.
  6313.  
  6314.               A problem may have been  encountered with version 1.0  if
  6315.           your program  changed text  modes.   The WINDOWS  unit  would
  6316.           dispose of  all  window  records, thus  corrupting  the  HELP
  6317.           unit's record of the on-line help system.  A call to TextMode
  6318.           now automatically resets the help system.
  6319.  
  6320.               The DATE unit has been modified to allow numeric dates to
  6321.           be forced to American or  British format, regardless of  what
  6322.           the system  configuration  may  be.    The  constants  to  be
  6323.           assigned to DateFormat have been altered to accommodate  this
  6324.           change.
  6325.  
  6326.               The TPU files  that were supplied  with version 1.0  were
  6327.           compiled  under  Turbo  Pascal  5.5.    To  avoid   potential
  6328.           confusion  for  people  using   different  versions  of   the
  6329.           compiler, the TPU files are not  now supplied.  A batch  file
  6330.           
  6331.           
  6332.                                       -107-  
  6333.           is now provided which will compile all six units.
  6334.  
  6335.               You may have also encountered  a problem with spacing  in
  6336.           the source code of version 1.0.   This was due to the use  of
  6337.           tabs  which  can  be  interpreted  differently  by  different
  6338.           editors.  All source code now  uses ASCII spaces in place  of
  6339.           tabs to avoid this problem.
  6340.  
  6341.  
  6342.  
  6343.           VERSION 2.0, May 1993
  6344.  
  6345.               This major revision of the library has introduced several
  6346.           additions and changes  to units  and seen a  revision of  the
  6347.           disk distribution  arrangement  and  example  support  files.
  6348.           Details of specific changes will be found in the  appropriate
  6349.           section of this manual.
  6350.  
  6351.               The Format function in the STRINGS unit has been extended
  6352.           to permit fractions to be displayed in vulgar form as well as
  6353.           decimals.  Several other options have also been added:  left-
  6354.           justification,  padding  with  a  definable  character,   and
  6355.           absolute value  display.   The method  for using  a  floating
  6356.           currency symbol has also been amended slightly, but you  will
  6357.           not need to change  your code unless  it previously used  the
  6358.           British pounds-sterling sign.  This change has also corrected
  6359.           a bug in  earlier versions that  prevented a zero-field  from
  6360.           being blanked with the "B"  option if the British symbol  was
  6361.           used.
  6362.  
  6363.               The new units MATH and MATH87 have been added to  provide
  6364.           measurement conversion routines.
  6365.  
  6366.               The DATE  and  TIME units  have  been integrated  into  a
  6367.           single unit  and several  new  subroutines have  been  added.
  6368.           These changes allow easier mixing of this package's  routines
  6369.           and Turbo  Pascal's library  routines for  handling  combined
  6370.           dates and  times.   The  TimeStr  function supports  two  new
  6371.           formats, TimeFormShort and  TimeFormShortSec.  The  constants
  6372.           relating to all time formats have been revised, so you should
  6373.           check any of your  code that uses  the old TimeStr  function.
  6374.           Date and time parsing have  also been extended to allow  null
  6375.           input to return  the current  date or time.   DateParse  will
  6376.           also now permit date entries  to default to the current  year
  6377.           and to allow two-digit  entry of 21st  century dates.   These
  6378.           options are controlled by global unit variables.  The default
  6379.           character assigned to TimeDelimiter for use by TimeStr is now
  6380.           a colon if your system is set to American configuration and a
  6381.           period if it is set to British configuration.
  6382.  
  6383.               A help-context stack has been added to the ENHCON unit to
  6384.           simplify the use of  context-sensitive help with  application
  6385.           programs  that  have  many   subroutines.    The   procedures
  6386.           
  6387.           
  6388.                                       -108-  
  6389.           PushHelpContext and PopHelpContext  have been implemented  to
  6390.           support this feature and two new error codes have been  added
  6391.           to the ConErr list.  Existing  code using version 1.1 of  the
  6392.           library will work  without change, although  you may wish  to
  6393.           take advantage of the new stack when updating your code.
  6394.  
  6395.               A bug has also been  discovered in ENHCON that  prevented
  6396.           the ConErrHelpInit error code from being reported properly if
  6397.           a call was made  to HelpInitialize when  the help system  was
  6398.           already initialized.  This has been corrected.
  6399.  
  6400.  
  6401.  
  6402.           VERSION 2.1, June 1993
  6403.  
  6404.               A compatibility  problem with  the new  Turbo Pascal  7.0
  6405.           compiler has  been  discovered.     Earlier versions  of  the
  6406.           library will falsely generate an "Out of memory" error when a
  6407.           null string is passed to the WriteWindow procedure in ENHCON,
  6408.           due to a change in the GETMEM routine from earlier compilers.
  6409.           Since WriteWindow is used by the windowing and help routines,
  6410.           you may  have also  experienced the  same problem  with  some
  6411.           other operations when using Turbo Pascal 7.0.  Version 2.1 of
  6412.           the library has corrected this problem.
  6413.  
  6414.  
  6415.  
  6416.  
  6417.  
  6418.  
  6419.  
  6420.  
  6421.  
  6422.  
  6423.  
  6424.  
  6425.  
  6426.  
  6427.  
  6428.  
  6429.  
  6430.  
  6431.  
  6432.  
  6433.  
  6434.  
  6435.  
  6436.  
  6437.  
  6438.  
  6439.  
  6440.  
  6441.  
  6442.           
  6443.           
  6444.                                       -109-  
  6445.  
  6446.  
  6447.  
  6448.  
  6449.  
  6450.  
  6451.  
  6452.  
  6453.  
  6454.  
  6455.  
  6456.  
  6457.  
  6458.  
  6459.  
  6460.  
  6461.  
  6462.  
  6463.  
  6464.  
  6465.  
  6466.  
  6467.  
  6468.  
  6469.  
  6470.  
  6471.  
  6472.  
  6473.  
  6474.  
  6475.  
  6476.  
  6477.  
  6478.  
  6479.  
  6480.  
  6481.  
  6482.  
  6483.  
  6484.  
  6485.  
  6486.  
  6487.  
  6488.  
  6489.  
  6490.  
  6491.  
  6492.  
  6493.  
  6494.  
  6495.  
  6496.  
  6497.  
  6498.           
  6499.           
  6500.                                       -110-  
  6501.                                    APPENDIX D.
  6502.                                DISTRIBUTION POLICY 
  6503.           =============================================================
  6504.  
  6505.  
  6506.               This package is released for free distribution and use by
  6507.           individuals or businesses.   My  reasons for  not charging  a
  6508.           registration fee are fairly simple: I am not in a position to
  6509.           provide full support for any of the software I write.  If you
  6510.           feel that you should make some sort of financial contribution
  6511.           for the software you use, then I suggest a donation of a  few
  6512.           dollars to a charity.
  6513.  
  6514.               Although there is no "official" support for this package,
  6515.           you are welcome to write with  any ideas or suggestions.   If
  6516.           you have any problems that you  think are caused by a bug  in
  6517.           the software, please feel free to write me and I will try  to
  6518.           help (letters to  England from the  United States require  50
  6519.           cents postage for the first half ounce).  If you just want to
  6520.           pass on a  short comment  or let me  know that  you find  the
  6521.           software useful, a picture-postcard from your home-town would
  6522.           be most welcome (40 cents postage).
  6523.  
  6524.               Please pass on copies of  this package to anyone who  may
  6525.           find it useful.
  6526.  
  6527.  
  6528.  
  6529.  
  6530.  
  6531.  
  6532.  
  6533.  
  6534.  
  6535.  
  6536.  
  6537.  
  6538.  
  6539.  
  6540.  
  6541.  
  6542.  
  6543.  
  6544.  
  6545.  
  6546.  
  6547.  
  6548.  
  6549.  
  6550.  
  6551.  
  6552.  
  6553.  
  6554.           
  6555.           
  6556.                                       -111-  
  6557.